我是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上运行它。 会导致这个问题吗?

堆栈跟踪:

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

#1楼 票数:4 已采纳

如果未在此位置抛出异常,则无法在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那样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)之间Files.isReadable(p) Files.list(p)

#2楼 票数:0

我相信您需要更改过滤器。 检查文件是否为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;
        }
    };
}

  ask by LakiGeri translate from so

未解决问题?本站智能推荐:

4回复

Java 8流中的聚合运行时异常

假设我有一个抛出运行时异常的方法。 我正在使用Stream在列表中的项目上调用此方法。 现在我希望处理列表中的所有项目,并将各个项目的任何运行时异常收集到最终将抛出的“聚合”运行时异常中。 在我的真实代码中,我正在进行第三方API调用,这可能会引发运行时异常。 我想确保处理所有
1回复

Java 8并行流如何在抛出的异常中运行?

Java 8并行流如何在forEach子句中的抛出异常上运行,例如在forEach处理中? 例如,以下代码: 它会立即停止处理元素吗? 是否等待已经启动的元素完成? 是否等待所有流完成? 抛出异常后是否开始处理流元素? 什么时候回来? 异常后立即? 毕竟/部分元素是由消
1回复

从嵌套哈希图中删除条目时,java中的ConcurrentModificationException [重复]

这个问题已经在这里有了答案: 迭代并从地图中删除[重复] 12个答案 这是一个示例代码,我试图从给定的Hashmap中删除null值。 但是这段代码给出了ConcurrentModificationException。 任何想法如何解决这个问题? 编辑:
2回复

将对象从函数返回值添加到列表时,Java 8 Stream 异常处理

我很难理解在使用 Java 8 流时如何处理异常。 我想将对象添加到一个空列表中,并且每个对象都从一个函数返回,该函数可能会根据输入的内容抛出异常。 如果仅针对输入列表中的某些值引发异常,我希望它继续遍历输入列表的其余部分。 使用 for 循环似乎很容易: 似乎可以使用 Java 流来实现这一点
2回复

如何映射Java流中的RuntimeExceptions以从无效流元素中“恢复”

想象一下,我正在构建一个将接收整数流的库,并且所有库代码需要做的是返回一个字符串流,其中包含数字的字符串表示形式。 但是,想象某人决定使用以下代码调用我的函数: 由于我希望我的API合约能够处理这种情况并且仍然返回一个字符串流,我想知道如何更改我的代码,以便它检测到流中存在异常并
3回复

Java如何比较谓词

我有两个建议: 使用 and if 语句,我如何确定我使用的是哪个谓词? 我正在尝试做这样的事情,但显然没有编译: 任何提示? 我对 Java 8 lambdas 很陌生 这是 Pojos 的代码(用于测试目的的简单继承):
1回复

Java 8由多个谓词总结

考虑以下使用Lombok注释注释的pojo类 要求是获取以下谓词的“ points”属性的LongSummaryStatistics : Predicate<User> adultMenPredicate = user -> Gender.MALE == use
2回复

在lambda中处理lambda中没有try-catch的异常

据我所知,如果lambda实现的抽象方法在其签名中没有throws ,则无法处理lambda中throws 。 我遇到以下代码,它的工作原理。 为什么openStream()不要求处理IOException ? 我可以在tryWithResources看到try-catch ,但我不明