压缩比例需手动计算:先用os.Stat获取原始文件和压缩文件的Size(),再求比值;最可靠方式是分别统计原始文件与压缩文件的字节数,而非依赖压缩包内声明的未压缩大小。

用 os.Stat 和手动计算原始/压缩后大小
Go 标准库不提供直接获取“压缩比例”的函数,因为压缩比例本身不是文件元数据,而是两个独立大小的比值。你需要自己读取原始文件和压缩后文件(如 .zip 或 .gz)的字节数,再做除法。
关键点是:原始大小 ≠ 压缩包内文件声明的未压缩大小(比如 ZIP 中的 UncompressedSize 字段可能被篡改或不准确),最可靠的方式是单独保存并统计原始文件的 os.Stat().Size()。
- 先用
os.Stat("input.txt").Size()获取原始大小 - 再用
os.Stat("input.txt.gz").Size()获取压缩后大小 - 压缩比例 =
float64(compressedSize) / float64(originalSize)(结果 - 注意:如果原始文件为空(0 字节),除零会 panic,需提前判断
解析 ZIP 文件时读取 FileHeader.UncompressedSize64
如果你处理的是 ZIP,并且信任归档内部元数据(例如自己生成的 ZIP),可以用 archive/zip 包提取每个文件头的 UncompressedSize64 和 CompressedSize64 字段来算单个文件的压缩比。
但要注意:UncompressedSize64 是 ZIP 规范里记录的原始大小,不一定等于磁盘上真实原始文件的大小(比如文件被截断后再打包、或使用了 ZIP64 扩展但解析不完整)。
立即学习“go语言免费学习笔记(深入)”;
- 用
zip.OpenReader打开 ZIP 文件 - 遍历
Reader.File列表,对每个*zip.File取f.UncompressedSize64和f.CompressedSize64 - 若
f.UncompressedSize64 == 0,可能是目录或损坏条目,跳过 - ZIP 中的压缩大小可能包含额外开销(如目录区、加密头),所以单文件比例 ≠ 整包压缩比例
处理 gzip 时不能依赖 gzip.Header 获取原始大小
gzip 格式在尾部有 8 字节的 ISIZE 字段,理论上存了原始未压缩大小的低 32 位,但 Go 的 compress/gzip 包默认不暴露这个值,gzip.Reader.Header 里没有 ISIZE 字段。
也就是说:你无法仅靠打开一个 .gz 文件就可靠还原原始大小——除非你事先知道,或者用外部工具(如 gzip -l)辅助。
- Go 标准库
gzip.Reader没有导出 ISIZE;gzip.Writer会写它,但读时不校验也不返回 - 强行读尾部 8 字节解析 ISIZE 是可行的,但需处理字节序、溢出(只存低 32 位)、以及文件是否被截断
- 更稳妥的做法仍是保留原始文件并
os.Stat对比
避免把“压缩率”误当成“压缩比”,单位别搞反
压缩比(compression ratio)通常定义为 原始大小 / 压缩后大小(>1 表示压缩有效),而压缩率(compression rate)常指 压缩后大小 / 原始大小(
- 输出时明确标注是
ratio (orig/compressed)还是rate (compressed/orig) - 不要四舍五入到整数——
0.23和0.27看似接近,实际差了 17% 的空间节省 - 如果要比较不同算法效果,确保原始文件完全一致(包括换行符、BOM、时间戳等无关但可能影响压缩率的细节)
真正麻烦的不是算除法,而是确认那两个分子分母到底代表什么——尤其是当压缩工具做了预处理(如去重、过滤空格)或用了非标准头格式时。


















