使用Java 7新IO获取文件/目录大小

54

如何使用Java 7中的新NIO获取文件或目录的大小?


旧方法有什么问题吗?除非现在支持递归目录大小。有吗? - Thilo
我听说它要快得多,我想试一下。 - clamp
我不得不想知道它怎么可能更快... - Thilo
我认为这是因为检查Java.io.File是否为目录的过程非常缓慢。 - clamp
@clamp:至少第二个问题确实可以通过使用“Path”来解决:由于它返回一个“Iterator”,因此在“iterator()”调用返回时,它不需要解析目录的所有成员,因此可以“流式传输”目录内容,这更符合大多数操作系统上的本机API。 - Joachim Sauer
显示剩余2条评论
3个回答

68

使用Files.size(Path)获取文件的大小。

对于目录的大小(即其中包含的所有文件的大小),据我所知,仍需要手动递归。


我认为Java7的I/O中不存在上述方法,请再检查一次。 - developer
2
@Damodar:我的回答包含JavaDoc链接。您为什么认为它不存在? - Joachim Sauer
2
他链接到了Oracle官方API文档。方法就在那里。 - Thilo
谢谢,那么我的下一个问题是,如何递归进入路径的子路径? - clamp
2
@clamp:一个Path 就是一个Iterable<Path>,所以你可以使用 for (Path child : parent) { /* 做一些事情 */ } 来遍历。 - Joachim Sauer

6
下面是一个可以直接运行的示例,它将跳过并记录无法进入的目录。它使用了java.util.concurrent.atomic.AtomicLong来累积状态。
public static void main(String[] args) throws IOException {
    Path path = Paths.get("c:/");
    long size = getSize(path);
    System.out.println("size=" + size);
}

static long getSize(Path startPath) throws IOException {
    final AtomicLong size = new AtomicLong(0);

    Files.walkFileTree(startPath, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path file,
                BasicFileAttributes attrs) throws IOException {
            size.addAndGet(attrs.size());
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc)
                throws IOException {
            // Skip folders that can't be traversed
            System.out.println("skipped: " + file + "e=" + exc);
            return FileVisitResult.CONTINUE;
        }
    });

    return size.get();
}

1
想知道为什么需要使用AtomicLong? 为什么不只使用long? walkFileTree是否有一些并行相关的东西? - peterh
说实话,我只是重新编写了另一个答案,而没有使用3pp(MutableLong)。但我认为变量必须是“final”才能从内部匿名类中访问。这可以通过使用AtomicLong来实现。 - Aksel Willgert
1
方法postVisitDirectory也可以被重写。这里不需要将size引用标记为final,因为它在内部匿名类中没有被改变。只有它的内容(值)被改变了。可以使用一个长数组(只有一个元素)来代替AtomicLong。 - Stephan

5
MutableLong size = new MutableLong();
Files.walkFileTree(directoryPath, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                size.add(attrs.size());
            }
}

这将计算目录中所有文件的大小。但是,请注意,目录中的所有文件都需要是常规文件,因为API指定了BasicFileAttributes的size方法:

"不是常规文件的文件大小是实现特定的,因此未指定。"

如果您遇到未受管制的文件,则必须要么不包含它的大小,要么返回一些未知的大小。您可以使用以下方式检查文件是否为常规文件:

BasicFileAttributes.isRegularFile()

好的答案,对于任何想知道 Mutable* 基本类型的类都是 apache.commons.lang 的一部分的人来说。 - Nicholi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接