获取文件夹或文件的大小

one*_*eat 99 java filesystems

如何在Java中检索文件夹或文件的大小?

Ten*_*she 183

java.io.File file = new java.io.File("myfile.txt");
file.length();
Run Code Online (Sandbox Code Playgroud)

这将返回文件的长度(以字节为单位)或0文件是否不存在.没有内置的方法来获取文件夹的大小,您将不得不递归地遍历目录树(使用listFiles()表示目录的文件对象的方法)并为自己累积目录大小:

public static long folderSize(File directory) {
    long length = 0;
    for (File file : directory.listFiles()) {
        if (file.isFile())
            length += file.length();
        else
            length += folderSize(file);
    }
    return length;
}
Run Code Online (Sandbox Code Playgroud)

警告:此方法对于生产用途而言不够稳健.directory.listFiles()可以返回null并引起NullPointerException.此外,它不考虑符号链接,可能还有其他失败模式.使用此方法.

  • 如果在Windows机器上的C:root目录中运行它,请小心; 那里有一个系统文件(根据java.io.File)既不是文件也不是目录.您可能希望更改else子句以检查File实际上是否是目录. (11认同)
  • 如果您使用Java 7或更高版本,请使用答案http://stackoverflow.com/a/19877372/40064它的速度要快得多. (3认同)
  • 简单的更改检查参数以查看它是否不是方法开头的目录并返回长度然后递归更简单 - 只需在同一方法中添加对self的调用,然后这支持传入文件引用而不是目录也是如此. (2认同)

Aks*_*ert 40

使用java-7 nio api,计算文件夹大小可以更快地完成.

这是一个准备好运行的示例,它是健壮的,不会抛出异常.它将记录它无法输入或无法遍历的目录.符号链接被忽略,并且目录的并发修改不会导致比必要更多的麻烦.

/**
 * Attempts to calculate the size of a file or directory.
 * 
 * <p>
 * Since the operation is non-atomic, the returned value may be inaccurate.
 * However, this method is quick and does its best.
 */
public static long size(Path path) {

    final AtomicLong size = new AtomicLong(0);

    try {
        Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {

                size.addAndGet(attrs.size());
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) {

                System.out.println("skipped: " + file + " (" + exc + ")");
                // Skip folders that can't be traversed
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) {

                if (exc != null)
                    System.out.println("had trouble traversing: " + dir + " (" + exc + ")");
                // Ignore errors traversing a folder
                return FileVisitResult.CONTINUE;
            }
        });
    } catch (IOException e) {
        throw new AssertionError("walkFileTree will not throw IOException if the FileVisitor does not");
    }

    return size.get();
}
Run Code Online (Sandbox Code Playgroud)

  • 我使用 JMH 做了一个基准测试,与 commons-io 代码相比,这个 NIO api 方法大约快 4 到 5 倍(在一个包含许多子文件夹的文件夹上测试,总共有 180229 个文件)。Commons IO 耗时 15 秒,NIO 耗时 5 秒。 (2认同)
  • 这种方法是最可靠的。它处理符号链接,并发修改,安全性异常,可同时用于文件和目录等。太糟糕了,“文件”不直接支持它! (2认同)

yeg*_*256 36

你需要FileUtils#sizeOfDirectory(File)commons-io.

请注意,您需要手动检查文件是否是目录,因为如果向其传递非目录,该方法将引发异常.

警告:此方法(从commons-io 2.4开始)有一个错误,IllegalArgumentException如果同时修改目录,则可能抛出该错误.

  • 请参阅bug [IO-449](https://issues.apache.org/jira/browse/IO-449).如果在迭代时修改目录,则此方法将抛出"IllegalArgumentException". (3认同)

And*_*ejs 18

在Java 8中:

long size = Files.walk(path).mapToLong( p -> p.toFile().length() ).sum();
Run Code Online (Sandbox Code Playgroud)

Files::size在map步骤中使用它会更好,但它会抛出一个已检查的异常.

更新:
您还应该知道,如果某些文件/文件夹不可访问,这可能会引发异常.使用Guava查看此问题和另一种解决方案.


Vis*_*hal 10

public static long getFolderSize(File dir) {
    long size = 0;
    for (File file : dir.listFiles()) {
        if (file.isFile()) {
            System.out.println(file.getName() + " " + file.length());
            size += file.length();
        }
        else
            size += getFolderSize(file);
    }
    return size;
}
Run Code Online (Sandbox Code Playgroud)


wum*_*mpz 6

对于Java 8,这是正确的方法:

Files.walk(new File("D:/temp").toPath())
                .map(f -> f.toFile())
                .filter(f -> f.isFile())
                .mapToLong(f -> f.length()).sum()
Run Code Online (Sandbox Code Playgroud)

过滤掉所有目录很重要,因为不能保证将length方法用于目录为0。

至少此代码提供与Windows Explorer本身相同的大小信息。


Eri*_*ran 5

这是获取一般文件大小的最佳方法(适用于目录和非目录):

public static long getSize(File file) {
    long size;
    if (file.isDirectory()) {
        size = 0;
        for (File child : file.listFiles()) {
            size += getSize(child);
        }
    } else {
        size = file.length();
    }
    return size;
}
Run Code Online (Sandbox Code Playgroud)

编辑:请注意,这可能是一项耗时的操作。不要在 UI 线程上运行它。

此外,这里(取自/sf/answers/391988971/)是从长返回中获取用户可读字符串的好方法:

public static String getReadableSize(long size) {
    if(size <= 0) return "0";
    final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" };
    int digitGroups = (int) (Math.log10(size)/Math.log10(1024));
    return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups))
            + " " + units[digitGroups];
}
Run Code Online (Sandbox Code Playgroud)