Вы не можете поймать исключение на Files.isRegularFile
, когда оно не выброшено в этом месте.Поскольку исключение выдается внутри кода, реализующего итерационную логику Files.walk
, вы можете перехватить его только в методе forEach
, когда он уже завершил всю операцию.
Вы можете реализовать логику итерации самостоятельноиметь больше контроля.Например,
public static Stream<Path> traverse(Path p, BiConsumer<Path,IOException> handler) {
if(Files.isDirectory(p)) try {
return Stream.concat(Stream.of(p),
Files.list(p).flatMap(sub -> traverse(sub, handler)));
} catch(IOException ex) {
handler.accept(p,ex);
}
return Stream.of(p);
}
, который вы можете использовать как
traverse(start, (p,ex) -> System.err.println(p+": "+ex))
.filter(Files::isRegularFile)
.forEach(System.out::println);
, чтобы распечатать исключение и продолжить, или
traverse(start, (p,ex) -> { throw new UncheckedIOException(ex); })
.filter(Files::isRegularFile)
.forEach(System.out::println);
, чтобы выручить как Files.walk
.
Когда вы знаете, что вас интересуют только обычные файлы, вы можете создать специальный метод, такой как
public static Stream<Path> traverseLeafs(Path p, BiConsumer<Path,IOException> handler) {
if(Files.isDirectory(p)) try {
return Files.list(p).flatMap(sub -> traverseLeafs(sub, handler));
} catch(IOException ex) {
handler.accept(p,ex);
return Stream.empty();
}
return Stream.of(p);
}
, который исключает каталоги прямо у источника.Вы все равно можете использовать filter(Files::isRegularFile)
, чтобы исключить специальные файлы, которые не являются ни каталогами, ни обычными файлами.
Вы также можете использовать Files.isDirectory(p) && Files.isReadable(p)
в качестве условия здесь, чтобы предотвратить появление AccessDeniedException
, по крайней мере, какПока флаги доступа не меняются между Files.isReadable(p)
и Files.list(p)
.