如何在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
相关产品推荐
相关产品推荐

