我正在使用一个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调用的,我希望确保没有留下任何句柄。


当前回答

从Java 7开始,你可以使用try-with-resources语句

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
}

因为BufferedReader实例是在try-with-resource语句中声明的,所以无论try语句是正常完成还是突然完成,它都将被关闭。所以你不需要在finally语句中自己关闭它。(对于嵌套的资源语句也是如此)

这是使用资源的推荐方式,有关更详细的信息,请参阅文档

其他回答

正如其他人指出的那样,您只需要关闭外部包装。

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

如果BufferedReader构造函数抛出异常(例如OutOfMemoryError),那么泄漏文件句柄的可能性非常小。如果你的应用处于这种状态,那么你的清理需要有多小心可能取决于你是否剥夺了操作系统可能想要分配给其他程序的资源。

在Java 5或6中,如果包装器构造函数可能失败,可以使用Closeable接口:

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

Java 7代码应该使用try-with-resources模式:

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

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

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

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

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

因此,只有bread .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;
        }
    }
}

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