我需要同时关闭FileReader和BufferedReader吗?


188

我正在使用包裹在FileReader周围的BufferedReader读取本地文件:

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

我需要close()FileReader为好,或将包装处理这个问题?我看过代码,人们在其中执行以下操作:

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

从Servlet调用此方法,并且我想确保我没有打开任何句柄。


4
您知道,您可以像这样阅读信息源。它全部位于JDK安装目录中的src.zip中,或者您可以从以下位置在线阅读它:docjar.com/html/api/java/io/BufferedReader.java.html
gustafc 2009年

50
告诉某人阅读源代码要比说“ RTFM!”差。如果源有错误,该怎么办?隐式地,我们想知道正确的行为是什么?
拉德瓦尔德

1
好吧……从这个角度来看:指向API规范并没有比这更好。如果源没有错误,导致其行为不像文档中指定的那样,则您不能依赖文档。因此,没有很好的方法来回答这样的问题。
Atmocreations

@Atmocreations如果仅查看源代码,下一个维护版本可以轻松修复您依赖的错误。您确实确实需要知道记录的行为是什么。当然,查看源代码没有错,但是您不能假设源代码不会改变。更改记录的行为通常比修复错误大得多。
詹姆斯·摩尔

Answers:


202

没有。

BufferedReader.close()

根据javadoc为BufferedReaderInputStreamReader 关闭流

以及

FileReader.close()

做。


12
除非构造函数BufferedReader抛出异常。尽管您需要提防带有其他资源和缓冲的装饰器,但仅关闭基础流是更清洁的方法。
汤姆·霍顿-钉路

9
Javadoc没有说明是否BufferedReader.close()关闭基础阅读器。它的描述仅从复制Reader.close()。这可能是实践中的实际行为,但没有记录。
约翰·库格曼

3
如果实际行为不同,则应将其记录在案。否则,文档将无用。程序员应该能够将文档视为完整而具体的文档。
Atmocreations

6
实际的文档是否已更改都没有关系,Reader#close()javadoc不会说是否关闭了它的包装好的Reader。它说的所有与之相关的Closes the stream and releases any system resources associated with it.内容还不够明确,以至于它没有或没有关闭资源。“释放资源”也可能会删除BufferedReader中对资源的任何引用...这将意味着资源未关闭。
searchengine27

99

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

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

如果BufferedReader构造函数抛出异常(例如OutOfMemoryError),则很有可能泄漏文件句柄。如果您的应用程序处于此状态,则清理的谨慎程度可能取决于您不剥夺操作系统可能要分配给其他程序的资源的重要性。

所述可关闭的,如果一个封装构造是可能在Java 5或6失败界面可用于:

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
}

1
“ Java 7代码应使用try-with-resources模式”。谢谢,这正是我想要的。此解决方案写于'09,因此“尝试使用资源”范例应该是新的建议。此外,相对于已接受且票数较高的答案,它为OP提供了更好的答案。
tresf

5

根据BufferedReader的消息来源,在这种情况下,bReader.close调用fReader.close,因此从技术上讲,您不必调用后者。


鉴于有说明如何使用它的文档,因此您应该首先查看该文档-代码中的任何偏差都是错误。
hmijail哀悼辞职者,

5

BufferedReader的源代码显示,当您关闭BufferedReader时,底层已关闭。


1
我真的很想为此链接到一个具体的东西,但这仅指的是OpenJDK的实现,并且由于JavaDocs不清楚Reader#close(),因此这并不能提供具体的证据,例如,Oracle JDK是在Oracle JDK中实现的。类似的时尚。
searchengine27

4

检查源代码后,我发现该示例:

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

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

因此,仅bReader.close()就足够了。


4
源代码显示的内容仅供参考。规范说的就是这种情况(在本例中为Javadoc),因此可以依靠。
罗恩侯爵,2015年

1

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

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

由于BufferedReader实例是在try-with-resource语句中声明的,因此无论try语句是正常完成还是突然完成,都将关闭该实例。因此,您无需在finally语句中自行关闭它。(嵌套资源语句也是如此)

这是使用资源的推荐方式,请参阅文档以获取更多详细信息


这几乎与@mcdowell在2009年的回答相同,后者也涵盖了可能发生的一些极端情况。
tresf


0

我迟到了,但是:

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

Eeeeh没有回答他/她的问题吗?她/他询问是否有必要关闭FileReader和BufferedReader而不是示例代码。
TornaxO7

@ TornaxO7不,这不是示例代码。我只是写了一部分Java源代码。因此,如果您使用ctrl / cmd键(取决于IDE)单击BufferedReader的某些功能,则可以看到BufferedReader的源代码,并且可以找到该代码段。因此,如您所见,BufferedReader本身仅关闭FileReader(在这种情况下,“ in”是FileReader,因此,当您调用bufferReader.close()时,它实际上在bufferReader.close方法中调用in.close())
Dmitry加什科

0

不要需要关闭包裹读/写器。

如果你已经采取了看看文档(Reader.close()Writer.close()),你会看到,Reader.close()它说:

关闭流并释放与其关联的所有系统资源。

只是说它“释放与其关联的所有系统资源”。即使它不能确认,也可以让您轻拍一下。如果您转到Writer.close()它,则仅说明它已关闭。

在这种情况下,我们将参考OpenJDK来查看源代码。

在BufferedWriter 265行,您将看到out.close()。因此,它不会自行关闭。还有其他事情。如果你搜索类的“出现次数out”你会发现,在构造函数中87号线out是作家的类包装它调用另一个构造函数,然后指定out参数,将其自身的out变量..

所以..其他人呢?您可以在BufferedReader行514BufferedInputStream行468InputStreamReader行199处看到类似的代码。我不知道的其他人,但这足以假设他们知道。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.