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

如何在Kotlin中获取Windows目录的Size on Disk(磁盘占用大小)?

获取Windows目录的磁盘占用大小(Size on Disk)

你当前的Kotlin代码计算的是文件实际内容总大小(对应Windows属性里的Size),而Size on Disk是文件占用磁盘簇的总空间——磁盘以固定大小的簇为单位分配存储,哪怕文件只有1字节,也会占用至少一个簇的空间。

下面提供两种在Kotlin中获取该值的可行方案:

方案1:解析Windows dir 命令输出

借助Windows内置的dir命令,通过指定参数获取递归的磁盘占用数据,再解析结果:

import java.io.BufferedReader
import java.io.InputStreamReader

fun getSizeOnDisk(path: String): Long {
    val process = ProcessBuilder("cmd.exe", "/c", "dir", path, "/s", "/-c", "/a-d")
        .redirectErrorStream(true)
        .start()
    
    BufferedReader(InputStreamReader(process.inputStream)).use { reader ->
        var total = 0L
        reader.lines().forEach { line ->
            // 匹配dir命令最后一行的总占用行,格式示例:"               12345678 字节"
            Regex("\\s+(\\d+) 字节").find(line)?.let {
                total = it.groupValues[1].toLong()
            }
        }
        return total
    }
}

// 使用示例
fun main() {
    val size = getSizeOnDisk("D:\\Games")
    println("磁盘占用大小: $size 字节")
}

注意:这种方式依赖dir命令的输出格式,不同语言版本的Windows可能存在差异,需要根据实际环境调整正则表达式。

方案2:调用Win32 API(更稳定可靠)

通过JNA直接调用Windows系统API,获取文件的簇分配信息,结果更准确且不依赖命令行:

首先在项目中添加JNA依赖(以Gradle为例):

implementation 'net.java.dev.jna:jna:5.13.0'
implementation 'net.java.dev.jna:jna-platform:5.13.0'

然后编写代码:

import com.sun.jna.platform.win32.*
import java.nio.file.Path

fun Path.getSizeOnDisk(): Long {
    val handle = Kernel32.INSTANCE.CreateFile(
        this.toString(),
        WinNT.GENERIC_READ,
        WinNT.FILE_SHARE_READ or WinNT.FILE_SHARE_WRITE or WinNT.FILE_SHARE_DELETE,
        null,
        WinNT.OPEN_EXISTING,
        WinNT.FILE_ATTRIBUTE_NORMAL,
        null
    )

    if (handle == WinNT.INVALID_HANDLE_VALUE) {
        throw RuntimeException("无法打开路径:$this,错误码:${Kernel32.INSTANCE.GetLastError()}")
    }

    return try {
        val allocInfo = Win32File.FILE_ALLOCATION_INFO()
        val buffer = allocInfo.toPointer()
        val success = Kernel32.INSTANCE.GetFileInformationByHandleEx(
            handle,
            Win32File.FileInfoByHandleClass.FileAllocationInfo,
            buffer,
            allocInfo.size().toInt()
        )
        if (!success) {
            throw RuntimeException("获取分配信息失败,错误码:${Kernel32.INSTANCE.GetLastError()}")
        }
        allocInfo.nNumberOfBytesAllocated.toLong()
    } finally {
        Kernel32.INSTANCE.CloseHandle(handle)
    }
}

fun getDirectoryTotalSizeOnDisk(path: Path): Long {
    return path.walk().sumOf { it.getSizeOnDisk() }
}

// 使用示例
fun main() {
    val dirPath = Path.of("D:\\Games")
    val totalSize = getDirectoryTotalSizeOnDisk(dirPath)
    println("目录磁盘总占用: $totalSize 字节")
}

说明:FILE_ALLOCATION_INFO.nNumberOfBytesAllocated就是单个文件/目录实际占用的磁盘空间,对目录递归遍历求和,就能得到整个目录的Size on Disk。

内容的提问来源于stack exchange,提问作者Cyber Avater

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 17:43:13