Files.walk(),计算总大小 [英] Files.walk(), calculate total size

查看:193
本文介绍了Files.walk(),计算总大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试计算光盘上文件的大小。在java-7中,这可以使用 Files.walkFileTree ,如我的回答所示这里

I'm trying to calculate the size of the files on my disc. In java-7 this could be done using Files.walkFileTree as shown in my answer here.

但是如果我想用java做这个-8 stream它适用于某些文件夹,但不适用于所有文件夹。

However if i wanted to do this using java-8 streams it will work for some folders, but not for all.

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:/ 它会抛出异常

Above code will work well for path a:/files/ but for c:/ it will throw below exception

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来避免它。

I understand where it is coming from and how to avoid it using Files.walkFileTree API.

但是如何使用 Files .walk() API?

But how can this exception be avoided using Files.walk() API?

推荐答案

不,这个例外无法避免。

No, this exception cannot be avoided.

异常本身发生在 Files.walk()的懒惰提取中,因此为什么你没有及早看到它以及为什么没有考虑以下代码:

The exception itself occurs inside the the lazy fetch of Files.walk(), hence why you are not seeing it early and why there is no way to circumvent it, consider the following code:

long size = Files.walk(Paths.get("C://"))
        .peek(System.out::println)
        .mapToLong(this::count)
        .sum();

在我的系统上,这将在我的电脑上打印:

On my system this will print on my computer:

C:\
C:\$Recycle.Bin
Exception in thread "main" java.io.UncheckedIOException: java.nio.file.AccessDeniedException: C:\$Recycle.Bin\S-1-5-18

作为异常被抛出在第三个文件的(主)线程上,该线程上的所有进一步执行都会停止。

And as an exception is thrown on the (main) thread on the third file, all further executions on that thread stop.

我认为这是一个设计失败,因为它现在站在 Files.walk 绝对无法使用,因为你无法保证在目标上行走时不会出现错误。

I believe this is a design failure, because as it stands now Files.walk is absolutely unusable, because you never can guarantee that there will be no errors when walking over a directory.

需要注意的一点是,堆栈跟踪包括 sum() reduce()操作,这是因为路径被延迟加载,所以在 reduce()时,大部分流机制被调用(在stacktrace中可见),然后它取出路径,此时 UnChecke发生了dIOException

One important point to notice is that the stacktrace includes a sum() and reduce() operation, this is because the path is being lazily loaded, so at the point of reduce(), the bulk of stream machinery gets called (visible in stacktrace), and then it fetches the path, at which point the UnCheckedIOException occurs.

如果让每个步行操作都在自己的线程上执行,那么可能可以被规避。但这不是你想要做的事情。

It could possibly be circumvented if you let every walking operation execute on their own thread. But that is not something you would want to be doing anyway.

另外,检查文件是否实际可访问毫无价值(虽然对于在某种程度上),因为你不能保证它甚至可以在1ms后读取。

Also, checking if a file is actually accessible is worthless (though useful to some extent), because you can not guarantee that it is readable even 1ms later.

我相信它仍然可以修复,但我不知道 FileVisitOption 是如何工作的。

目前有一个 FileVisitOption。 FOLLOW_LINKS ,如果它基于每个文件运行,那么我怀疑还可以添加 FileVisitOption.IGNORE_ON_IOEXCEPTION ,但是我们无法正确注入那里的功能。

I believe it can still be fixed, though I do not know how FileVisitOptions exactly work.
Currently there is a FileVisitOption.FOLLOW_LINKS, if it operates on a per file basis, then I would suspect that a FileVisitOption.IGNORE_ON_IOEXCEPTION could also be added, however we cannot correctly inject that functionality in there.

这篇关于Files.walk(),计算总大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆