GetCompressedFileSize返回的是NTFS压缩后磁盘占用字节数,非压缩比例;须先用GetFileAttributes检查FILE_ATTRIBUTE_COMPRESSED标志,否则结果无意义,且对非NTFS卷、加密或稀疏文件行为未定义。

GetCompressedFileSize 返回值比实际大?先确认文件是否真被压缩
这个函数不返回“压缩比例”,它只返回 NTFS 压缩后文件在磁盘上占用的字节数(即“压缩后的逻辑大小”),和 GetFileSize 返回的原始大小对比才能算出比例。但很多人直接拿 GetCompressedFileSize 结果当“压缩后体积”,结果发现比原始大小还大——那说明文件根本没被 NTFS 压缩,或者压缩失败了。
- 必须先用
GetFileAttributes检查FILE_ATTRIBUTE_COMPRESSED标志是否置位,否则GetCompressedFileSize的返回值无意义 - 该函数对非 NTFS 卷(如 FAT32、exFAT、网络共享)总是返回原始大小,不报错也不提示
- 对加密文件(
FILE_ATTRIBUTE_ENCRYPTED)或稀疏文件,行为未定义,建议跳过
GetCompressedFileSize 在 Windows 10/11 上返回错误?检查调用方式
常见错误是传入了无效句柄或忽略错误码。它不抛异常,只靠返回值和 GetLastError() 判断成败。
- 必须用
CreateFile以GENERIC_READ权限打开,且不能带FILE_FLAG_NO_BUFFERING(否则返回 0 +ERROR_INVALID_PARAMETER) - 返回值为
INVALID_FILE_SIZE(即0xFFFFFFFF)时,立刻调GetLastError():常见是ERROR_ACCESS_DENIED(权限不足)、ERROR_SHARING_VIOLATION(文件被独占打开) - 64 位程序注意:函数原型返回
DWORD,但实际高位可能存于lpFileSizeHigh输出参数,必须用双参数重载版本GetCompressedFileSizeEx(Windows 8+)或自己拼LARGE_INTEGER
怎么算出真正的压缩比例?别直接除
比例不是简单用 GetCompressedFileSize 除以原始大小。NTFS 压缩按簇(cluster)对齐,小文件即使压缩后只剩几十字节,也可能占满一个簇(比如 4KB),导致比例失真。
- 原始大小用
GetFileSizeEx获取LARGE_INTEGER,避免 32 位截断 - 压缩后大小也必须用
GetCompressedFileSizeEx(推荐)或正确处理高低 32 位 - 若原始大小为 0,比例无定义;若压缩后大小 ≥ 原始大小,说明未压缩或压缩膨胀(如已加密/高熵数据),此时比例应视为 1.0
- 示例计算逻辑:
double ratio = (double)compressedSize / (double)originalSize; if (compressedSize >= originalSize || originalSize == 0) ratio = 1.0;
替代方案:为什么有时 GetCompressedFileSize 不够用
它只反映 NTFS 文件系统级压缩,对 ZIP、7z 等应用层压缩包完全无效——你拿到的只是 ZIP 文件自身的大小,不是里面内容的压缩率。
立即学习“C++免费学习笔记(深入)”;
- 想分析 ZIP 内部文件压缩比?得用 libzip 或 miniz 解包后读
uncompressed_size/compressed_size字段 - 想监控实时压缩效果?NTFS 没提供回调机制,只能轮询或监听 USN 日志(复杂且开销大)
- 跨平台需求?该 API 是 Windows-only,Linux/macOS 需依赖
stat.st_blocks * st_blksize(不精确,且受文件系统影响大)
真正难的不是调用函数,而是搞清你要的“压缩比例”到底属于哪一层:文件系统、归档格式,还是自定义算法。拿错层级的数据去算,结果再准也没用。



















