BufferedReader 和 InputStreamReader 是不是应该显式关闭?
Posted
技术标签:
【中文标题】BufferedReader 和 InputStreamReader 是不是应该显式关闭?【英文标题】:Should BufferedReader and InputStreamReader be closed explicitly?BufferedReader 和 InputStreamReader 是否应该显式关闭? 【发布时间】:2018-05-01 01:10:40 【问题描述】:我想将InputStream
的内容读入String
:
private String readToString(InputStream stream)
return new BufferedReader(new InputStreamReader(stream))
.lines().collect(Collectors.joining("\n"));
流来自java.lang.Process
。
问题:在这种情况下,我是否必须明确关闭 InputStream
、InputStreamReader
或 BufferedReader
中的任何一个?
旁注:链接的问题 NOT 重复,因为我的问题是关于 HOW 正确关闭流,而不是如何将流读取到字符串!
【问题讨论】:
javadoc forlines
似乎暗示流不会自动关闭。
不要关闭任何东西。如果关闭 BufferedReader 或 InputStreamReader,它们也会隐式关闭 InputStream。但这个责任应该由打开它的人承担(最好是在 try-with-resources 中)。此外,如果您想将整个文本读入一个字符串,请不要逐行阅读,只是为了将这些行重新组合成一个字符串。换行符没有什么特别之处,这应该意味着文件必须像这样拆分。相反,将整个文件读取为字节并使用您选择的编码将它们转换为字符。
@KlitosKyriacou 这个问题是从 2008 年开始的,已经快 10 年了
@DodgyCodeException 实际上,即使问题很旧,其中的一些答案也是最近的!其中一个答案使用 Java 9 功能。
我刚刚看到您的编辑,并认为您认为这个问题不是重复的。我撤回了我的近距离投票。
【参考方案1】:
您只需要关闭 outer
包装器,但无论哪种方式都不要明确地这样做 - 有 try-with-resource 可以让您的生活更轻松:
public String readToString(InputStream stream)
try (InputStreamReader reader = new InputStreamReader(stream);
BufferedReader br = new BufferedReader(reader))
return br.lines().collect(Collectors.joining("\n"));
catch (IOException e)
e.printStackTrace();
throw new RuntimeException(e);
还有一种更更简单且更清晰的方法:
Files.readAllLines(YourPath)
【讨论】:
我从java.lang.process so cannot use
Files 获取输入流。但是试一下没问题。【参考方案2】:
根据我的评论,关闭 BufferedReader 或 InputStreamReader 将导致 InputStream 被关闭。您的 readToString
方法不应关闭流。这是调用者的责任。
理由:-
首先,在调用readToString
之前,请考虑如何打开流。一个明智的做法是:
try (InputStream myStream = getInputStreamSomehow())
//...
String content = readToString(myStream);
//...
流将在您的 try-with-resources 块结束时关闭。
其次,考虑现有的最佳做法和习语。看看 Java API 方法,就像您的方法一样,读取流的全部内容。例如,从 Java 9 开始:
readAllBytes()
transferTo(OutputStream out)
上述方法都不会关闭流。同样,readToString
方法的用户不会期望您关闭他们的流。
【讨论】:
以上是关于BufferedReader 和 InputStreamReader 是不是应该显式关闭?的主要内容,如果未能解决你的问题,请参考以下文章