问题
geniuses!
I'm practicing Java 8.
So if I do something like this:
Files.walk(Paths.get(corpusPathStr))
.filter(path -> path.toFile().isFile())
.forEach(path -> {
try {
Files.lines(path)
.forEach(...);
} catch (IOException e) {
e.printStackTrace();
}
});
I got FileSystemException error.
If I open a file under forEach, may too many files be opened?
Or are there other reasons causing FileSystemException (Too many open files)?
Thanks for your help in advance!
回答1:
Use
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();
}
The streams returned by Files.walk
and Files.lines
must be properly closed to release the resources, which you do by either, a try(…)
construct or returning them in the mapping function of a flatMap
operation.
Don’t use nested forEach
s.
The UncheckedIOException
might not only be thrown by our mapping function, but also the stream implementations. Translating it back to an IOException
allows to treat them all equally.
回答2:
Files::line
opens and reads the file in a lazy manner, i.e. Stream<String>
. Since you're not closing any of your opened Stream
s you're getting such an error.
So when you're done reading a file you should close its handle. Since the returned Stream
is AutoCloseable
you can and should use a try-with-resource block.
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();
}
来源:https://stackoverflow.com/questions/43067269/java-8-path-stream-and-filesystemexception-too-many-open-files