我正在尝试计算光盘上文件的大小。在 java-7 中,这可以使用文件.walkFileTree http://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#walkFileTree-java.nio.file.Path-java.nio.file.FileVisitor-如我的回答所示here https://stackoverflow.com/questions/7255592/get-file-directory-size-using-java-7-new-io/19869323#comment32024328_19869323.
但是,如果我想使用 java-8 流来执行此操作,它将适用于某些文件夹,但不适用于所有文件夹。
public static void main(String[] args) throws IOException {
long size = Files.walk(Paths.get("c:/")).mapToLong(MyMain::count).sum();
System.out.println("size=" + size);
}
static long count(Path path) {
try {
return Files.size(path);
} catch (IOException | UncheckedIOException e) {
return 0;
}
}
上面的代码适用于路径a:/files/
但对于c:/
它会抛出以下异常
Exception in thread "main" java.io.UncheckedIOException: java.nio.file.AccessDeniedException: c:\$Recycle.Bin\S-1-5-20
at java.nio.file.FileTreeIterator.fetchNextIfNeeded(Unknown Source)
at java.nio.file.FileTreeIterator.hasNext(Unknown Source)
at java.util.Iterator.forEachRemaining(Unknown Source)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Unknown Source)
at java.util.stream.AbstractPipeline.copyInto(Unknown Source)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
at java.util.stream.AbstractPipeline.evaluate(Unknown Source)
at java.util.stream.LongPipeline.reduce(Unknown Source)
at java.util.stream.LongPipeline.sum(Unknown Source)
at MyMain.main(MyMain.java:16)
我了解它来自哪里以及如何使用 Files.walkFileTree API 避免它。
但是如何使用来避免这个异常文件.walk() http://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#walk-java.nio.file.Path-java.nio.file.FileVisitOption...- API?
不,这个异常是无法避免的。
异常本身发生在延迟获取中Files.walk()
,因此为什么您没有尽早看到它以及为什么没有办法规避它,请考虑以下代码:
long size = Files.walk(Paths.get("C://"))
.peek(System.out::println)
.mapToLong(this::count)
.sum();
在我的系统上,这将打印在我的计算机上:
C:\
C:\$Recycle.Bin
Exception in thread "main" java.io.UncheckedIOException: java.nio.file.AccessDeniedException: C:\$Recycle.Bin\S-1-5-18
当第三个文件的(主)线程上抛出异常时,该线程上的所有进一步执行都会停止。
我相信这是一个设计失败,因为就目前情况而言Files.walk
绝对无法使用,因为你永远不能保证遍历目录时不会出现错误。
需要注意的一个重要点是堆栈跟踪包括sum()
and reduce()
操作,这是因为路径正在被延迟加载,所以在这一点上reduce()
,大部分流机制被调用(在堆栈跟踪中可见),然后它获取路径,此时UnCheckedIOException
occurs.
它可以possibly如果您让每个步行操作在自己的线程上执行,则可以避免这种情况。但无论如何,这都不是您想做的事情。
另外,检查文件是否确实可访问是毫无价值的(虽然在某种程度上有用),因为你不能保证它在1ms后仍然可读。
未来的扩展
我相信它仍然可以修复,尽管我不知道如何修复FileVisitOption
确实有效。
目前有一个FileVisitOption.FOLLOW_LINKS
,如果它在每个文件的基础上运行,那么我会怀疑FileVisitOption.IGNORE_ON_IOEXCEPTION
也可以添加,但是我们无法正确地将该功能注入其中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)