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

JavaIoBufferedreaderFilereader

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

no.

BufferedReader.close()

closes the stream according to javadoc for BufferedReader and InputStreamReader

as well as

FileReader.close()

does.

Solution 2 - Java

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 - Java

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

Solution 4 - Java

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

Solution 5 - Java

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.

Solution 6 - Java

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

Solution 7 - Java

You Only Need to close the bufferedReader i.e reader.close() and it will work fine .

Solution 8 - Java

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;
        }
    }
}

Solution 9 - Java

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.

Solution 10 - Java

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).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZilkView Question on Stackoverflow
Solution 1 - JavaAtmocreationsView Answer on Stackoverflow
Solution 2 - JavaMcDowellView Answer on Stackoverflow
Solution 3 - JavaBrian AgnewView Answer on Stackoverflow
Solution 4 - JavaCsaba_HView Answer on Stackoverflow
Solution 5 - JavaAnup VermaView Answer on Stackoverflow
Solution 6 - JavaClaudiu MateiView Answer on Stackoverflow
Solution 7 - JavaJitendraView Answer on Stackoverflow
Solution 8 - JavaDmitry GashkoView Answer on Stackoverflow
Solution 9 - JavaOmar Abdul'AzeezView Answer on Stackoverflow
Solution 10 - JavajstrickerView Answer on Stackoverflow