我正在使用一个BufferedReader包装FileReader读取一个本地文件:

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

我是否需要关闭()FileReader,或者包装器将处理它? 我曾见过这样的代码:

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

这个方法是从servlet调用的,我希望确保没有留下任何句柄。


当前回答

在您的场景中,只需要关闭BufferedReader。

正如其他人指出的那样,JavaDocs是模棱两可的。当你想要立即调用close时,使用try-with-resources块是最好的方法,但如果你需要保持读取器打开,它就不起作用了(例如,一个类有一个方法,返回一个使用底层读取器的流——调用close通常是调用方的责任)。

如果您无法访问源代码,并且希望查看您的阅读器和JVM调用在您的情况下是否关闭各种阅读器和流,那么可以将close方法重写为一个简单的测试。

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();

当你运行上面的程序时,你会看到类似的结果:

BufferedReader::close()
InputStreamReader::close()
FileInputStream::close()

由于JavaDoc中没有编写明确的规范,我们无法确定所有jvm的行为。然而,大多数阅读器/流似乎都遵循上述模式(例如,你可以在上面的例子中添加一个GZIPInputStream,并看到GZIPInputStream::close()也会被调用)。

其他回答

根据BufferedReader源代码,在这种情况下,bReader。近距离呼叫fReader。关闭,从技术上讲,您不必调用后者。

no.

BufferedReader.close()

根据javadoc关闭BufferedReader和InputStreamReader的流

还有

FileReader.close()

所做的事。

你只需要关闭bufferedReader,即reader.close(),它就会工作得很好。

我迟到了,但是:

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

在检查源代码后,我发现对于这个例子:

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

BufferedReader对象上的close()方法将调用Reader类的抽象close()方法,该方法最终将调用InputStreamReader类中实现的方法,然后关闭InputStream对象。

因此,只有bread .close()是足够的。