Do I need to close() both FileReader and BufferedReader?

I'm reading a local file using a BufferedReader wrapped around a FileReader:

BufferedReader reader = new BufferedReader(new FileReader(fileName));
// read the file
// (error handling snipped)
reader.close();

Do I need to close() the FileReader as well, or will the wrapper handle that? I've seen code where people do something like this:

FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);
// read the file
// (error handling snipped)
bReader.close();
fReader.close();

This method is called from a servlet, and I'd like to make sure I don't leave any handles open.


Solution 1:

no.

BufferedReader.close()

closes the stream according to javadoc for BufferedReader and InputStreamReader

as well as

FileReader.close()

does.

Solution 2:

As others have pointed out, you only need to close the outer wrapper.

BufferedReader reader = new BufferedReader(new FileReader(fileName));

There is a very slim chance that this could leak a file handle if the BufferedReader constructor threw an exception (e.g. OutOfMemoryError). If your app is in this state, how careful your clean up needs to be might depend on how critical it is that you don't deprive the OS of resources it might want to allocate to other programs.

The Closeable interface can be used if a wrapper constructor is likely to fail in Java 5 or 6:

Reader reader = new FileReader(fileName);
Closeable resource = reader;
try {
  BufferedReader buffered = new BufferedReader(reader);
  resource = buffered;
  // TODO: input
} finally {
  resource.close();
}

Java 7 code should use the try-with-resources pattern:

try (Reader reader = new FileReader(fileName);
    BufferedReader buffered = new BufferedReader(reader)) {
  // TODO: input
}

Solution 3:

The source code for BufferedReader shows that the underlying is closed when you close the BufferedReader.

Solution 4:

According to BufferedReader source, in this case bReader.close call fReader.close so technically you do not have to call the latter.

Solution 5:

After checking the source code, I found that for the example:

FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);

the close() method on BufferedReader object would call the abstract close() method of Reader class which would ultimately call the implemented method in InputStreamReader class, which then closes the InputStream object.

So, only bReader.close() is sufficient.