Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is java.io.BufferedOutputStream safe to use?

Tags:

java

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)
like image 392
Evgeniy Dorofeev Avatar asked Jan 23 '13 10:01

Evgeniy Dorofeev


People also ask

What is the use of BufferedOutputStream in Java?

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.

Why BufferedOutputStream?

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.

Why should we use BufferedOutputStream with FileOutputStream?

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.

What is BufferedOutputStream true?

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.


1 Answers

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.

like image 143
pcalcao Avatar answered Oct 06 '22 01:10

pcalcao