Do terminal operations close the stream?

后端 未结 2 486
旧巷少年郎
旧巷少年郎 2020-12-03 07:41

dirPath contains 200k files. I want to read them one by one and do some processing. The following snippet causes java.nio.file.FileSystemException: dirPat

相关标签:
2条回答
  • 2020-12-03 07:56

    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 -> { });
    }
    
    0 讨论(0)
  • 2020-12-03 08:04

    No forEach does not close the stream (created by Files.list or Files.lines). It is documented in the javadoc, for example for Files.list:

    The returned stream encapsulates a Reader. If timely disposal of file system resources is required, the try-with-resources construct should be used to ensure that the stream's close method is invoked after the stream operations are completed.

    0 讨论(0)
提交回复
热议问题