避免( java.nio.file.AccessDeniedException )的 Java 8 Files.walk(..) 终止原因 [重复]

Posted

技术标签:

【中文标题】避免( java.nio.file.AccessDeniedException )的 Java 8 Files.walk(..) 终止原因 [重复]【英文标题】:Avoid Java 8 Files.walk(..) termination cause of ( java.nio.file.AccessDeniedException ) [duplicate] 【发布时间】:2017-10-15 20:46:28 【问题描述】:

我正在使用 Java 8 Files.walk(..) 来计算文件夹中包含的 .mp3 文件以及其中的所有文件夹。换句话说,我正在访问文件树的所有级别。

当我收到java.nio.file.AccessDeniedException Stream 关闭时,我不想要这种行为。我需要它忽略或打印异常并继续计数文件。以下是我使用的代码:):

   /**
     * Count files in a directory (including files in all sub
     * directories)
     * 
     * @param directory
     *        the directory to start in
     * @return the total number of files
     */
    public int countFiles(File dir) 
        if (dir.exists())
            try (Stream<Path> paths = Files.walk(Paths.get(dir.getPath()), FileVisitOption.FOLLOW_LINKS)) 
                return (int) paths.filter(path -> 

                    // i am using something different here but i changed
                    // it just for the purpose of *** question                                
                    return path.toString().contains(".mp3");

                ).count();
             catch (IOException ex) 
                //Main.logger.log(Level.WARNING, "", ex);
                ex.printStackTrace();
            

        return 0;
    

错误堆栈跟踪:

java.io.UncheckedIOException: java.nio.file.AccessDeniedException: C:\$Recycle.B
in\S-1-5-18
    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.jav
a:1801)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.LongPipeline.reduce(LongPipeline.java:438)
    at java.util.stream.LongPipeline.sum(LongPipeline.java:396)
    at java.util.stream.ReferencePipeline.count(ReferencePipeline.java:526)
    at smartcontroller.SmartController$InputService$1.countFiles(SmartController.ja
va:2092)
...

类似的问题,虽然不一样,但我需要返回一个 Stream

Working around access denied in a FileWalking Tree in Java7 。


【问题讨论】:

在您链接到的副本中使用 non-try-with-resources 版本 @JarrodRoberson 我需要一个Stream,这样我才能使用Java8 方法。你能发表一个关于它的答案吗:)? 您的代码无法编译,在 try 块内有一些杂乱的代码(return 和 count() 什么都没有引用)。请发布正确的内容,让我们正确地帮助您:) @JarrodRoberson 你好 Jarrod :),我阅读了您发布的副本的链接。虽然这不是我要寻找的。异常来自try (Stream&lt;Path&gt; paths = Files.walk(Paths.get(dir.getPath()), FileVisitOption.FOLLOW_LINKS)),所以无论我做什么都会抛出异常。 我需要在内部修复 Files.walk(...) 。所以它可能是重复的,但不是你标记的那种重复......你有任何想法都可以将它作为答案发布。 我同意这与链接的副本无关。重新开放。 【参考方案1】:

回答

这是一个临时解决方案,可以改进为使用 Java 8 Streams 和 Lambdas。

int[] count = 0;
try 
    Files.walkFileTree(
            Paths.get(dir.getPath()), 
            new HashSet<FileVisitOption>(Arrays.asList(FileVisitOption.FOLLOW_LINKS)),
            Integer.MAX_VALUE, new SimpleFileVisitor<Path>() 
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 
                        throws IOException 
                    System.out.printf("Visiting file %s\n", file);
                    ++count[0];
                    return FileVisitResult.CONTINUE;
                
                
                @Override
                public FileVisitResult visitFileFailed(Path file, IOException e) 
                        throws IOException 
                    System.err.printf("Visiting failed for %s\n", file);
                    return FileVisitResult.SKIP_SUBTREE;
                
                
                @Override
                public FileVisitResult preVisitDirectory(Path dir,
                                                         BasicFileAttributes attrs) 
                        throws IOException 
                    System.out.printf("About to visit directory %s\n", dir);
                    return FileVisitResult.CONTINUE;
                
            );
 catch (IOException e) 
    // handle exception

【讨论】:

你好,我看到这个列表所有文件,很好,如何获取目录大小,每个第一个目录?并且只列出第一级? 有一个选项叫做 max depth :) logicbig.com/how-to/code-snippets/…,你需要稍微修改一下代码来满足你的需要。您可以在 *** 上提出问题并将链接发送给我,以便我回答。 您好@GOXR3PLUS,感谢您的关注。 ***.com/questions/55830126/… 只是为了澄清从visitFileFailed()返回SKIP_SUBTREE是没有意义的。只有从preVisitDirectory()返回时才有意义 是的 - 至少是下半场:) 只是跳过目录的能力只能preVisitDirectory() 中决定。尝试从 file 中跳过目录失败的行为与继续相同。

以上是关于避免( java.nio.file.AccessDeniedException )的 Java 8 Files.walk(..) 终止原因 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

正确使用@Async,避免踩坑

避免插入失败以避免虚假的自动增量

如何避免两次编写 SQL Server 查询以避免重复?

MYSQL的UPDATE子查询,UPDATE时避免使用子查询

DDoS攻击是啥?应该如何避免?

Delphi 中要避免的组件