当我执行在流管道期间打开大量文件的代码时:
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);
}
我得到一个例外:
java.nio.file.FileSystemException: /long/file/name: Too many open files
问题是Stream.count
当它完成遍历它时不会关闭它。但我不明白为什么它不应该,因为它是一个终端操作。这同样适用于其他终端操作,例如reduce
和forEach
。flatMap
另一方面关闭它包含的流。
文档告诉我在必要时使用 try-with-resouces-statement 关闭流。在我的情况下,我可以用这样的count
东西替换该行:
.map(s -> { long c = s.count(); s.close(); return c; } )
但这既吵闹又丑陋,在某些大型复杂管道的情况下可能会带来真正的不便。
所以我的问题如下:
- 为什么没有设计流以使终端操作关闭他们正在处理的流?这将使它们更好地处理 IO 流。
- 关闭管道中的 IO 流的最佳解决方案是什么?
runtimizeException
是一种将检查的异常包装在RuntimeException
s 中的方法。