Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it necessary to call close() in a finally when writing files in Java?

Tags:

java

android

There are a few examples where people call close() in their finally block when writing to a file, like this:

OutputStream out = null;
try {
    out = new FileOutputStream(file);
    out.write(data);
    out.close();
}
catch (IOException e) {
    Log.e("Exception", "File write failed: " + e.toString());
} finally {
    try {
        if (out != null) {
            out.close();
        }
    } catch (IOException e) {
        Log.e("Exception", "File write failed: " + e.toString());
    }
}

But there are many more examples, including the official Android docs where they don't do that:

try {
    OutputStream out = new FileOutputStream(file);
    out.write(data);
    out.close();
}
catch (IOException e) {
    Log.e("Exception", "File write failed: " + e.toString());
}

Given that the second example is much shorter, is it really necessary to call close() in finally as shown above or is there some mechanism that would clean up the file handle automatically?

like image 531
AndreKR Avatar asked Jan 07 '23 03:01

AndreKR


2 Answers

Every situation is a little bit different, but it's best to always close in a finally block OR use java's try with resources syntax, which is effectively the same thing.

The risk you run by not closing in the finally block is that you end up with an unclosed stream object after the catch gets triggered. Also, if your stream is buffered, you might need that final close to flush the buffer to ensure that the write is fully complete. It may be a critical error to complete without that final close.

like image 166
Doug Stevenson Avatar answered Jan 08 '23 18:01

Doug Stevenson


Not closing the file may mean the stream contents don't get flushed in a timely way. This is a concern in the case that the code completes normally and doesn't throw an exception.

If you don't close a FileOutputStream, then its finalize method will try to close it. However, finalize doesn't get called immediately, it is not guaranteed to get called at all, see this question. It would be better not to rely on this.

If JDK7's try-with-resources is an option then use it:

try (OutputStream out = new FileOutputStream(file);) {
    out.write(data);
}

Otherwise, for JDK6, make sure the exception thrown on close can't mask any exception thrown in the try block:

OutputStream out = new FileOutputStream(file);
try {
    out.write(data);
} finally {
    try {
        out.close();
    } catch (IOException e) {
        Log.e("Exception", "File write failed: " + e.toString());
    }
}

It may be verbose but it makes sure the file gets closed.

like image 42
Nathan Hughes Avatar answered Jan 08 '23 17:01

Nathan Hughes