views:

1402

answers:

5

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.

A: 

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

Csaba_H
+13  A: 

no.

BufferedReader.close()

closes the stream according to javadoc for BufferedReader and InputStreamReader

as well as

FileReader.close()

does.

Atmocreations
+1 for combination of succinctness and clarity.
CPerkins
Unless the constructor to `BufferedReader` throws an exception. It's cleaner just to close the underlying stream, although you need to watch out for decorators with other resources and buffering.
Tom Hawtin - tackline
A: 

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

Brian Agnew
+4  A: 

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:

Reader reader = new FileReader(fileName);
Closeable resource = reader;
try {
  BufferedReader buffered = new BufferedReader(reader);
  resource = buffered;
  // TODO: input
} finally {
  resource.close();
}
McDowell
Thank you, that was very enlightening.
Zilk
A: 

Best practice is using using keyword to work with disposable objects (which implements IDispose), like this:

using (FileReader fReader = new FileReader(fileName))
using (BufferedReader bReader = new BufferedReader(fReader))
{
  // read the file
  // (error handling snipped)
}

Using block will care itself about closing objects and cleaning used memory, even if exception occurs.

Veton
i believe the OP was referring to Java which doesn't have the "using" construct. Java 7 is supposed to add this to the language. Can't wait.
Matt
Right, author speaks about Java. Sorry:)
Veton