为什么在try-with-resources?</string>中获取`Stream <string>`时BufferedReader没有关闭

时间:2013-12-02 01:18:34

标签: java java-8 java-stream try-with-resources autocloseable

在try-with-resources中使用Stream时,应关闭阅读器。

鉴于此:

try(Stream<String> lines = new BufferedReader(reader).lines()) {
            return lines.map(it -> trim ? it.trim() : it)
                    .collect(Collectors.toList());
}

......读者没有被关闭?

此测试失败:

    AtomicBoolean closed = new AtomicBoolean(false);

    Reader r = new StringReader("  Line1 \n Line2") {

                @Override
                public void close() {
                    super.close();
                    closed.set(true);
                }

            };

    try(Stream<String> lines = new BufferedReader(r).lines()) {
            lines.map(it -> trim ? it.trim() : it)
                    .collect(Collectors.toList());
    }

    assertTrue("Reader was not closed.",closed.get());

2 个答案:

答案 0 :(得分:8)

我实际上并没有使用try-resources语法。希望我的回答有道理。

根据我的理解,自动关闭正在关闭声明中声明的资源,没有别的。

因此,try(Stream<String> lines = new BufferedReader(r).lines()) {只是关闭lines,而不是那个没有分配变量的缓冲读者。

如果你打算关闭缓冲的阅读器和流(你真的需要关闭流吗?),iirc,你可以在try语句中有多行:

try (BufferedReader br = new BufferedReader(r);
     Stream<String> lines = br.lines()) {
    //....
}
这样的事情。 (没有尝试编译,希望它有效:P)

答案 1 :(得分:0)

虽然这不是您问题的即时答案,但它可以确保之后关闭所有资源。

受到 Guava 的 CharSource.lines() 实现的启发,该实现使用关闭处理程序 Stream.onClose(Runnable) 在处理的流关闭时关闭相应的 BufferedReader 并且
Stream.flatMap(...) 的特性(感谢这个 trick

<块引用>

在其内容放入后调用 BaseStream.close() 这个流。

您可以获得在终端操作后自动关闭的行流。

Stream<String> lines = lines(reader);
// ..


Stream<String> lines(Reader reader) {
    BufferedReader br = new BufferedReader(reader);
    Stream<String> lines = br.lines()
            .onClose(() -> {
                try {
                    br.close();
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            });
    return Stream.of(lines).flatMap(s -> s); // Autocloseable exploit of Stream.flatMap()
}