Reputation: 9285
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.
Upvotes: 216
Views: 209343
Reputation: 2180
You need to close only the BufferedReader
in your scenario.
As others have pointed out, the JavaDocs are ambiguous. Using the try-with-resources block is the best approach when you want close
to be called right away, but it doesn't work if you need to keep the reader open (e.g. a class that has a method that returns a stream which uses an underlying reader--it would generally be the caller's responsibility to call close
there).
If you don't have access to the source code and want to see whether your reader and JVM calls close
on the various readers and streams in your situation, you could override the close
method as a simple test.
Path path = Paths.get("/home/example/test.txt");
InputStream fileInputStream = new FileInputStream(path.toFile()) {
public void close() throws IOException {
System.out.println("FileInputStream::close()");
super.close();
}
};
Reader inputStreamReader = new InputStreamReader(fileInputStream, Charsets.UTF_8) {
public void close() throws IOException {
System.out.println("InputStreamReader::close()");
super.close();
}
};
BufferedReader bufferedReader = new BufferedReader(inputStreamReader) {
public void close() throws IOException {
System.out.println("BufferedReader::close()");
super.close();
}
};
bufferedReader.close();
When you run the above, you'll see something very similar to:
BufferedReader::close()
InputStreamReader::close()
FileInputStream::close()
Since there is no explicit specification written in the JavaDoc, we can't be certain of the behavior across all JVMs. However, most of readers/streams seem to follow the above pattern (e.g. you can add a GZIPInputStream
to the above example and see that GZIPInputStream::close()
also gets called).
Upvotes: 0
Reputation: 173
You Don't need to close the wrapped reader/writer.
If you've taken a look at the docs (Reader.close()
,Writer.close()
), You'll see that in Reader.close()
it says:
Closes the stream and releases any system resources associated with it.
Which just says that it "releases any system resources associated with it". Even though it doesn't confirm.. it gives you a nudge to start looking deeper. and if you go to Writer.close()
it only states that it closes itself.
In such cases, we refer to OpenJDK to take a look at the source code.
At BufferedWriter Line 265 you'll see out.close()
. So it's not closing itself.. It's something else. If you search the class for occurences of "out
" you'll notice that in the constructor at Line 87 that out
is the writer the class wraps where it calls another constructor and then assigning out
parameter to it's own out
variable..
So.. What about others? You can see similar code at BufferedReader Line 514, BufferedInputStream Line 468 and InputStreamReader Line 199. Others i don't know but this should be enough to assume that they do.
Upvotes: 1
Reputation: 300
I'm late, but:
BufferReader.java:
public BufferedReader(Reader in) {
this(in, defaultCharBufferSize);
}
(...)
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close();
} finally {
in = null;
cb = null;
}
}
}
Upvotes: 0
Reputation: 4101
Starting from Java 7 you can use try-with-resources Statement
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
Because the BufferedReader
instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly. So you don't need to close it yourself in the finally
statement. (This is also the case with nested resource statements)
This is the recomanded way to work with resources, see the documentation for more detailed information
Upvotes: 3
Reputation: 183
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.
Upvotes: 7
Reputation: 52
You Only Need to close the bufferedReader i.e reader.close() and it will work fine .
Upvotes: 0
Reputation: 10071
no.
BufferedReader.close()
closes the stream according to javadoc for BufferedReader and InputStreamReader
as well as
FileReader.close()
does.
Upvotes: 220
Reputation: 108969
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
}
Upvotes: 113
Reputation: 272417
The source code for BufferedReader shows that the underlying is closed when you close the BufferedReader.
Upvotes: 7
Reputation: 8245
According to BufferedReader source, in this case bReader.close call fReader.close so technically you do not have to call the latter.
Upvotes: 7