At first glance this code seems completely OK
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("1.txt"));
byte[] bytes = new byte[4096];
bout.write(bytes);
bout.close();
but if we take a closer look we will see that close()
is implemented as follows
public void close() throws IOException {
try {
flush();
} catch (IOException ignored) {
}
out.close();
}
Is it possible that due to flush()
errors are ignored data may be lost and the program will not notice it? There is no mentioning of any danger in FilterOutputStream.close
(where BufferedOutputStream
inherits close()
from) API.
UPDATE: To simulate IO error during close() I changed the test to write to a Flash memory, added a 5 secs sleep before bout.close() and while the test was sleeping I removed the Flash from USB. The test finished without exceptions, but when I inserted the Flash and checked it - 1.txt was not there.
Then I overrode close()
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("g:/1.txt")) {
@Override
public void close() throws IOException {
flush();
super.close();
}
};
and ran the test again and got
Exception in thread "main" java.io.FileNotFoundException: g:\1.txt (The system cannot the specified path)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:212)
at java.io.FileOutputStream.<init>(FileOutputStream.java:104)
at test.Test1.main(Test1.java:10)
BufferedOutputStream(OutputStream out) : Creates a new buffered output stream to write data to the specified underlying output stream. BufferedOutputStream(OutputStream out, int size) : Creates a new buffered output stream to write data to the specified underlying output stream with the specified buffer size.
BufferedOutputStream provides output data buffering which increases efficiency by storing values to be written in a buffer and actually writing them out when the buffer fills or when the flush() method is called.
BufferedOutputStream helps when the writes are smaller than the buffer size e.g. 8 KB. For larger writes it doesn't help nor does it make it much worse. If ALL your writes are larger than the buffer size or you always flush() after every write, I would not use a buffer.
BufferedOutputStream is a class in Java which we can use to write data into the output stream. It uses a buffer to write data instead of directly writing into the file. We can use the FileOutputStream class along with the BufferedOutputStream to write information to the file.
As it is, I would reason that calling close
can indeed make you lose data, since that potential IOException
is being silently ignored (who on earth knows what went through the developers minds to do that...).
A decent alternative, although it does put the effort on the side of the programmer, is to call flush
explicitly before close
(handling the potential IOException
correctly), like mentioned in a comment by @Tom, particularly in a try/finally
block.
This problem can be further exacerbated in Java7, due to AutoCloseable
objects, since you won't explicitly call the close()
method and this kind of work-around is even easier to slip by.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With