4

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

鉴于这种:

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());
4

2 回答 2

10

我实际上并没有使用 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)

于 2013-12-02T01:31:44.140 回答
1

虽然这不是您问题的直接答案,但它确保所有资源之后都关闭。

受到 GuavaCharSource.lines()实现的启发,该实现使用关闭处理程序Stream.onClose(Runnable)在处理的流关闭时关闭相应的 BufferedReader 以及
Stream.flatMap(...)感谢这个技巧

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()
}
于 2021-03-11T08:38:43.463 回答