Java 8 Path Stream和FileSystemException(打开的文件太多)

Gyu*_*hoi 4 nio java-8

天才!

我正在练习Java 8.

所以,如果我做这样的事情:

Files.walk(Paths.get(corpusPathStr))
        .filter(path -> path.toFile().isFile())
        .forEach(path -> {
            try {
                Files.lines(path)
                        .forEach(...);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
Run Code Online (Sandbox Code Playgroud)

我收到了FileSystemException错误.

如果我在forEach下打开一个文件,可能会打开太多文件?

或者是否有其他原因导致FileSystemException(打开文件过多)?

感谢您的帮助!

Flo*_*own 7

Files::line打开并以懒惰的方式读取文件,即Stream<String>.由于你没有关闭任何已打开的Streams,你会收到这样的错误.

因此,当您完成阅读文件后,您应该关闭它的句柄.由于返回的StreamAutoCloseable你可以而且应该使用try-with-resource块.

try (Stream<Path> walk = Files.walk(Paths.get(""))) {
  walk.filter(Files::isRegularFile).forEach(path -> {
    try (Stream<String> lines = Files.lines(path)) {
      lines.forEach(System.out::println);
    } catch (IOException e) {
      e.printStackTrace();
    }
  });
} catch (IOException e) {
  e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)


Hol*_*ger 5

使用

try(Stream<Path> stream = Files.walk(Paths.get(corpusPathStr))) {
    stream.filter(path -> Files.isRegularFile(path) && Files.isReadable(path))
          .flatMap(path -> {
                       try { return Files.lines(path); }
                       catch (IOException e) { throw new UncheckedIOException(e); }
                   })
          .forEach(...);
}
catch(UncheckedIOException ex) {
    throw ex.getCause();
}
Run Code Online (Sandbox Code Playgroud)

这些流通过返回Files.walkFiles.lines必须正确关闭,以释放资源,您可以通过任一做,一个try(…)结构或在映射函数返回他们flatMap的操作.

不要使用嵌套forEach的.

UncheckedIOException可能不仅是我们的映射功能被抛出,而且流实现.将其翻译成一个IOException允许平等对待它们.

  • @GyuHyeon Choi:流是懒惰的,所以这将处理一个接一个的文件(除非你启用并行处理,这意味着每个线程处理一个文件的可能性). (2认同)