You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java中获取目录在磁盘上的实际占用空间(Linux环境)

如何在Java中获取目录在磁盘上的实际占用空间(Linux环境)

这个问题我之前处理小文件密集的目录时也踩过坑!确实FileUtils.sizeOf()只是简单累加所有文件的逻辑字节大小,完全没考虑磁盘的块分配机制——哪怕是1字节的小文件,也会占用至少一个磁盘块,再加上目录本身的存储开销,结果和du命令的真实占用差几十上百倍太正常了。

下面给你两种可行的解决方案:

方案一:直接调用Linux的du命令(推荐)

既然是Linux环境,直接用系统原生的du命令是最省心也最准确的选择,它会自动处理块大小、目录条目、inode开销这些细节。我们可以通过Java的ProcessBuilder来执行命令并解析结果:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class DiskUsageCalculator {
    public static long getActualDirectorySize(String dirPath) throws IOException {
        // 使用du -sb命令:-s汇总目录总大小,-b按字节输出结果
        ProcessBuilder processBuilder = new ProcessBuilder("du", "-sb", dirPath);
        Process process = processBuilder.start();

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String outputLine = reader.readLine();
            if (outputLine != null) {
                // 输出格式是"大小 路径",分割后取第一个数字
                return Long.parseLong(outputLine.split("\\s+")[0]);
            }
        } finally {
            process.destroy();
        }
        return -1; // 读取失败返回-1
    }

    public static void main(String[] args) throws IOException {
        long size = getActualDirectorySize("/path/to/your/directory");
        System.out.println("实际占用空间:" + size + " 字节");
    }
}

这个方法的优点是:完全适配Linux文件系统的特性,结果和du命令完全一致,代码量少不用自己造轮子;唯一的小缺点是依赖系统命令,跨平台性差,但你已经明确是Linux环境,这点可以忽略。

方案二:纯Java实现(手动计算块占用)

如果不想依赖系统命令,也可以自己通过Java NIO API来计算。核心思路是:

  1. 获取文件系统的块大小
  2. 遍历所有文件和目录,计算每个文件实际占用的块数(逻辑大小向上取整到块大小的倍数)
  3. 加上目录本身的实际占用空间

代码示例如下:

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public class PureJavaDiskUsage {
    public static long calculateActualSize(Path directory) throws IOException {
        FileStore fileStore = Files.getFileStore(directory);
        long blockSize = fileStore.getBlockSize(); // 获取磁盘块大小
        long totalSize = 0;

        // 遍历目录下所有文件和子目录
        Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                long fileLogicalSize = attrs.size();
                // 计算实际占用的块数:向上取整
                long occupiedBlocks = (fileLogicalSize + blockSize - 1) / blockSize;
                totalSize += occupiedBlocks * blockSize;
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                if (exc == null) {
                    // 计算目录本身的实际占用空间
                    BasicFileAttributes dirAttrs = Files.readAttributes(dir, BasicFileAttributes.class);
                    long dirLogicalSize = dirAttrs.size();
                    long occupiedBlocks = (dirLogicalSize + blockSize - 1) / blockSize;
                    totalSize += occupiedBlocks * blockSize;
                }
                return FileVisitResult.CONTINUE;
            }
        });

        return totalSize;
    }

    public static void main(String[] args) throws IOException {
        Path dirPath = Paths.get("/path/to/your/directory");
        long actualSize = calculateActualSize(dirPath);
        System.out.println("实际占用空间:" + actualSize + " 字节");
    }
}

不过要注意,这个纯Java实现可能和du的结果有细微差异——因为有些文件系统的inode、扩展属性等额外开销,Java API可能无法完全覆盖,所以如果追求绝对准确,还是优先用方案一。

备注:内容来源于stack exchange,提问作者chris01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 11:28:07