Предикат Java8 с try catch - PullRequest
       9

Предикат Java8 с try catch

0 голосов
/ 12 октября 2018

Я новичок в потоковом слове java8, но я хочу это понять.Сделав несколько простых вещей, я пошел глубже, поэтому мне нравится перечислять все файлы в папке.Я получил идею от здесь .

    Files.walk(start)
        .filter(Files::isRegularFile)
        .forEach(System.out::println);

Это работает хорошо, но я запустил эту папку, где находится какой-то файл спецификаций, и выдает AccessDeniedException.Я сделал некоторый поиск, и я знаю, что это не простая проблема.Я пытаюсь обработать исключение следующим образом:

private static Predicate<Path> fillAccessDenied() {
    return p -> {
        try {
            if(Files.isRegularFile(p)) {                    
                return true;                
            } else {
                return false;
            }
        } catch (UncheckedIOException e) {
            e.printStackTrace();
            return false;
        }
    };
}
  //....
    Files.walk(start)
        .filter(Utils.fillAccessDenied())
        .forEach(System.out::println);

Но проблема остается, и я не понимаю, почему.Может кто-нибудь подсказать мне, в чем здесь проблема?

Заранее спасибо!

РЕДАКТИРОВАТЬ:

Я вынул систему между попыткамиловить, но проблема остается.

public static void println(Object x) {

    try {
        String s = String.valueOf(x);
        System.out.println(s);
    } catch (UncheckedIOException e) {
        e.printStackTrace();
    }
}

//...

    Files.walk(start)
        .filter(Utils.fillAccessDenied())
        .forEach(Utils::println);

Мой путь ввода "/", и я запускаю его на Linux.Это вызывает эту проблему?

stacktrace:

java.io.UncheckedIOException: java.nio.file.AccessDeniedException: /etc/sysconfig/network/providers
    at java.nio.file.FileTreeIterator.fetchNextIfNeeded(FileTreeIterator.java:88)
    at java.nio.file.FileTreeIterator.hasNext(FileTreeIterator.java:104)
    at java.util.Iterator.forEachRemaining(Iterator.java:115)
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
    at hu.gergelylakatos.jbackupper.JBackupper.main(JBackupper.java:45)
Caused by: java.nio.file.AccessDeniedException: /etc/sysconfig/network/providers
    at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
    at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
    at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
    at sun.nio.fs.UnixFileSystemProvider.newDirectoryStream(UnixFileSystemProvider.java:427)
    at java.nio.file.Files.newDirectoryStream(Files.java:457)
    at java.nio.file.FileTreeWalker.visit(FileTreeWalker.java:300)
    at java.nio.file.FileTreeWalker.next(FileTreeWalker.java:372)
    at java.nio.file.FileTreeIterator.fetchNextIfNeeded(FileTreeIterator.java:95)
    ... 10 more

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

Вы не можете поймать исключение на 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).

0 голосов
/ 12 октября 2018

Я считаю, что вам нужно изменить свой фильтр.Проверка наличия файла isRegular не означает, что вы не получите AccessException.

Убедитесь, что вы фильтруете папки.

private static Predicate<Path> fillAccessDenied() {
    return p -> {
        try {
            if(Files.isReadable(p) && !Files.isDirectory(p)) {                    
                return true;                
            } else {
                return false;
            }
        } catch (UncheckedIOException e) {
            e.printStackTrace();
            return false;
        }
    };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...