关闭Stream会关闭BufferedReader源吗?

时间:2015-06-16 08:36:57

标签: java stream

来自the docs

  

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

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

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

// Is the BufferedReader, InputStreamReader and InputStream closed?

我尝试过的一些非常快速的测试说不(in的{​​{1}}字段不是BufferedReader),但后来我对以下句子感到困惑,因为这个例如I / O,对吧?

  

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

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

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

3 个答案:

答案 0 :(得分:5)

如果您想将阅读器的关闭推迟到交付的流,您需要调用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

的任何引用

答案 2 :(得分:2)

在您的问题中,您没有展示如何创建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);
        }        
    }
}