gpt4 book ai didi

java - 在管道中间关闭流

转载 作者:IT老高 更新时间:2023-10-28 20:40:33 25 4
gpt4 key购买 nike

当我执行在流管道期间打开大量文件的代码时:

public static void main(String[] args) throws IOException {
Files.find(Paths.get("JAVA_DOCS_DIR/docs/api/"),
100, (path, attr) -> path.toString().endsWith(".html"))
.map(file -> runtimizeException(() -> Files.lines(file, StandardCharsets.ISO_8859_1)))
.map(Stream::count)
.forEachOrdered(System.out::println);
}

我得到一个异常(exception):

java.nio.file.FileSystemException: /long/file/name: Too many open files

问题是 Stream.count 在遍历完流后并没有关闭它。但我不明白为什么它不应该,因为它是一个终端操作。这同样适用于其他终端操作,例如 reduceforEach。另一方面,flatMap 会关闭它所包含的流。

文档告诉我在必要时使用 try-with-resouces-statement 关闭流。在我的情况下,我可以用这样的东西替换 count 行:

.map(s -> { long c = s.count(); s.close(); return c; } )

但这又吵又丑,在某些大型复杂管道的情况下可能会带来真正的不便。

所以我的问题如下:

  1. 为什么没有设计流以使终端操作关闭他们正在处理的流?这将使它们更好地处理 IO 流。
  2. 关闭管道中的 IO 流的最佳解决方案是什么?

runtimizeException 是一种将检查的异常包装在 RuntimeExceptions 中的方法。

最佳答案

这里有两个问题:处理已检查的异常,例如 IOException ,并及时关闭资源。

没有一个预定义的函数式接口(interface)声明任何检查异常,这意味着它们必须在 lambda 中处理,或者包装在未经检查的异常中并重新抛出。看起来像您的 runtimizeException功能就是这样做的。您可能还必须为它声明自己的功能接口(interface)。您可能已经发现,这很痛苦。

在关闭诸如文件之类的资源时,有一些关于在到达流末尾时自动关闭流的调查。这会很方便,但它不处理抛出异常时的关闭。在流中并没有神奇的“做正确的事”机制。

我们只剩下处理资源关闭的标准 Java 技术,即 Java 7 中引入的 try-with-resources 构造。TWR 确实希望资源在同一级别关闭在它们打开时的调用堆栈中。 “谁开谁关”的原则适用。 TWR 还处理异常处理,这通常便于在同一个地方处理异常处理和资源关闭。

在本例中,流有点不寻常,因为它映射了 Stream<Path>Stream<Stream<String>> .这些嵌套流是未关闭的流,当系统用完打开的文件描述符时会导致最终异常。使这变得困难的是文件由一个流操作打开,然后传递到下游;这使得无法使用 TWR。

构建此管道的另一种方法如下。

Files.lines call 是打开文件的那个,所以这必须是 TWR 语句中的资源。这个文件的处理在哪里(一些)IOExceptions被抛出,所以我们可以在同一个 TWR 语句中进行异常包装。这表明有一个简单的函数将路径映射到行数,同时处理资源关闭和异常包装:

long lineCount(Path path) {
try (Stream<String> s = Files.lines(path, StandardCharsets.ISO_8859_1)) {
return s.count();
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
}

有了这个辅助函数后,主管道如下所示:

Files.find(Paths.get("JAVA_DOCS_DIR/docs/api/"),
100, (path, attr) -> path.toString().endsWith(".html"))
.mapToLong(this::lineCount)
.forEachOrdered(System.out::println);

关于java - 在管道中间关闭流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22921623/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com