【问题标题】:Does closing a Stream close the BufferedReader source?关闭 Stream 是否会关闭 BufferedReader 源?
【发布时间】:2015-08-31 23:25:51
【问题描述】:

来自the docs

Streams 有一个 BaseStream.close() 方法并实现 AutoCloseable, 但几乎所有流实例实际上都不需要关闭 使用后。通常,只有源为 IO 通道的流(例如 因为 Files.lines(Path, Charset)) 返回的那些将需要关闭。 大多数流由集合、数组或生成器支持 功能,不需要特殊的资源管理。 (如果一个流 确实需要关闭,它可以声明为一个资源 try-with-resources 语句。)

当我在BufferedReader 上使用lines() 方法创建Stream<String> 时,如下所示,关闭Stream 是否也会关闭BufferedReader

try (Stream<String> lines = new BufferedReader(new InputStreamReader(process.getInputStream())).lines()) {
  // Do stuff
}

// Is the BufferedReader, InputStreamReader and InputStream closed?

我尝试过的一些非常快速的测试说不(BufferedReaderin 字段不是null),但是我被下面的句子弄糊涂了,因为这个例子是 I/O嗯,对吧?

通常,只有源是 IO 通道的流(例如 因为 Files.lines(Path, Charset)) 返回的那些需要关闭。

如果没有,我是否需要关闭 两个 实例,或者关闭 BufferedReader 就足够了?


理想情况下,我想从某个方法返回一个Stream&lt;String&gt;,而不必让客户担心读者。目前,我创建了一个 Stream 装饰器,它也关闭了阅读器,但如果没有必要,它会更容易。

【问题讨论】:

  • 您在哪里测试BufferedReader 是否已关闭?在try 块内?
  • 我在Stream 上显式调用close 后对其进行了测试,并使用调试器检查了该字段。自动关闭尝试是我想如何使用它的一个例子。

标签: java stream


【解决方案1】:

如果您想延迟关闭阅读器到交付的 Stream,您需要调用 Stream.onClose()

static Stream<String> toStream(BufferedReader br){
    return br.lines().onClose(asUncheckedAutoCloseable(br));
}


static Runnable asUncheckedAutoCloseable(AutoCloseable ac) {
    return () -> {
        try {
            ac.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    };
}

【讨论】:

  • 稍微编辑了你的答案......希望你不介意 - 我当之无愧的 1+
【解决方案2】:

不,似乎没有。由于流是使用

创建的
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
            iter, Spliterator.ORDERED | Spliterator.NONNULL), false);

不传递任何对BufferedReader的引用

【讨论】:

  • 问题中没有调用public static Stream&lt;String&gt; lines(Path path, Charset cs)Reader.lines() 被调用。
  • 这似乎是一个令人信服的论点,说明为什么BufferedReader 不会从Stream 中关闭。查看lines 的来源,我看不出必须关闭Stream 的理由,我得出结论,只有BufferedReader 应该关闭。
  • 关于你问题的第二部分 - 试试Files.lines(Path, Charset)
  • 不幸的是,我不是从文件中读取,而是从流程流中读取。
【解决方案3】:

在您的问题中,您没有展示您如何创建Reader,这是new BufferedReader(in) 的论点。但根据我自己的测试,没有理由假设 Stream 关闭了这个论点。

执行以下操作会关闭所有人:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.stream.Stream;

public class SOPlayground {

    public static void main(String[] args) throws Exception {
        try (Reader in = new InputStreamReader(new FileInputStream(new File("/tmp/foo.html")));
                BufferedReader reader = new BufferedReader(in);
                Stream<String> lines = reader.lines()) {
            lines.forEach(System.out::println);
        }        
    }
}

【讨论】:

  • 谢谢,我也找到了。我在问题中添加了一些附加信息。
  • 使用try(Stream&lt;String&gt; lines = Files.lines(Paths.get("/tmp/foo.html"))) {...}会简单得多。
  • 请记住,Tagir,OP 的用例不是从文件中读取,而是从进程的InputStream 中读取。
猜你喜欢
  • 2010-11-02
  • 1970-01-01
  • 2014-12-04
  • 1970-01-01
  • 2015-09-19
  • 2012-12-12
  • 2018-05-01
相关资源
最近更新 更多