终端操作是否关闭了流?

时间:2014-11-18 14:55:02

标签: java-8 java-stream

dirPath包含200k个文件。我想逐个阅读它们并做一些处理。以下代码段会导致java.nio.file.FileSystemException: dirPath/file-N Too many open files。在移动到下一个操作之前,终端操作forEach()是否应关闭开放流(即打开文件)?换句话说,我是否必须为流式文件添加try-with-resources?

Files.list(dirPath)
     .forEach(filePath -> {
              Files.lines(filePath).forEach() { ... }
              });

2 个答案:

答案 0 :(得分:16)

forEach不关闭流(由Files.listFiles.lines创建)。它记录在javadoc中,例如Files.list

  

返回的流封装了一个Reader。如果需要及时处理文件系统资源,则应使用try-with-resources构造来确保在流操作完成后调用流的close方法。

答案 1 :(得分:7)

A nested forEach is the wrong tool, in most cases.

The code

Files.list(dirPath).forEach(filePath -> Files.lines(filePath).forEach(line -> { ... });

can and should be replaced by

Files.list(dirPath).flatMap(filePath -> Files.lines(filePath)).forEach(line -> { ... });

or well, since it’s not that easy in this case:

Files.list(dirPath).flatMap(filePath -> {
    try { return Files.lines(filePath);}
    catch(IOException ex) { throw new UncheckedIOException(ex); }
}).forEach(line -> {  });

as a side-effect, you get the following for free:

Stream.flatMap(…):

Each mapped stream is closed after its contents have been placed into this stream.

So that’s the preferred solution. Or well, to make it entirely correct:

try(Stream<Path> dirStream = Files.list(dirPath)) {
    dirStream.flatMap(filePath -> {
        try { return Files.lines(filePath);}
        catch(IOException ex) { throw new UncheckedIOException(ex); }
    }).forEach(line -> { });
}