软件工具

zip 中文乱码怎么治:7-Zip 与系统自带实测

🐨硬盘收藏家 LV1 · 3 次浏览 · 0 条回复

上周给朋友拷一包剧,字幕、nfo、海报都在,压缩完发过去,他在 Mac 上一解,中文名全成了方块和问号。文件本身没坏,就是名字没法用。我本来想随口回一句「用 7-Zip 压就不会乱码」,结果自己动手一测,发现这句话是错的——7-Zip 命令行版默认写进 zip 的东西,恰好是乱码的根源之一。

既然工具都装好了,速度就顺手一起量了,因为「该用哪个压缩工具」的另一半答案在耗时和内存上。

测的是什么

两个目录,都是真实文件,不是造的数据。

  • 目录 A:本项目依赖目录,1677 个文件、177MB,其中 565 个 .js,其余是 .md、.json、.map,典型的「碎文件 + 文本」
  • 目录 B:一个 258MB 的影视目录,含 256MB 已压制的码流、一份 srt、一个 1.4MB 的预告片

机器是 Ryzen 5 3550H、16GB 内存、SATA SSD、Win11。参与对比的四个工具:

  • 7-Zip 25.01,用官方 Extra 包里的 7za.exe,压缩包本身只有 1.6MB
  • Windows 自带的「右键 → 压缩为 ZIP」,用 Compress-Archive 复现同一个流程
  • Windows 11 自带的 tar.exe,实际是 bsdtar 3.8.9
  • 每项跑完记墙钟耗时,同时每 100 毫秒采一次进程内存,取峰值

zip 中文乱码怎么治:7-Zip 与系统自带实测

速度:系统自带 40.7 秒,7-Zip 的 zip 只用 21 秒

目录 A,177MB、1677 个文件:

  • 7z 固实 mx=5:72.9 秒,压完 39.13MB
  • 7z 固实 mx=9:79.1 秒,37.01MB
  • 7z 非固实 mx=5:66.8 秒,40.86MB
  • zip mx=5、8 线程:21.1 秒,56.41MB
  • zip mx=9、8 线程:131.2 秒,55.69MB
  • zip mx=1、8 线程:4.58 秒,59.69MB
  • zip mx=5、单线程:36.6 秒,56.41MB
  • bsdtar:12.6 秒,58.16MB
  • 系统自带 Optimal:40.7 秒,58.03MB
  • 系统自带 Fastest:31.0 秒,64.88MB

先看最常用的那条:右键压缩。40.7 秒、58.03MB。同一批文件交给 7-Zip 的 zip 模式,21.1 秒、56.41MB——时间少一半,体积还小 1.6MB。也就是说右键压缩唯一的好处是「不用装软件」,性能上两头都不占。

再看 -mx=9。这个参数在论坛里被当成「压得更狠」的银弹,实测是纯坑:131.2 秒,比 mx=5 慢 6.2 倍,体积只从 56.41MB 降到 55.69MB,省下 0.72MB,1.3%。原因不复杂,zip 的 deflate 是每个文件独立压缩,档位只影响单个文件内部的搜索强度,跨文件一点不共享,天花板本来就在那儿。

反而 mx=1 值得一说:4.58 秒压完,59.69MB。比 mx=5 只大 3.3MB,速度是它的 4.6 倍。给朋友传、当天就删的包,用这个档最划算。

bsdtar 12.6 秒,是全场最快,比 7-Zip 的 zip 还快 1.7 倍。它默认多线程、实现也轻,但它的中文名有问题,下面单独说。

还有一组数据能说明「多线程」这件事被高估了:zip mx=5 单线程 36.6 秒,8 线程 21.1 秒,只快了 1.73 倍,不是 8 倍。zip 是按文件分块并行的,1677 个文件里大半是几百字节的小文件,线程开满也在排队等磁盘和杀毒软件扫新文件。

固化压缩省得比想象少

7z 固实 39.13MB,非固实 40.86MB,只差 1.73MB,4.2%,代价是多花 6 秒。固实压缩(把多个文件连成一条流再压)的收益主要来自「很多内容高度相似的小文件」,比如同一个模板生成的几百个 html;我这批依赖文件差异太大,长距离匹配基本用不上。

真正拉开差距的是内存:

  • 7z mx=9 固实:峰值 1238MB
  • 7z mx=5 固实:494MB
  • 7z mx=5 非固实:387MB
  • zip 8 线程:80MB
  • zip 单线程:15.4MB
  • bsdtar:7.1MB
  • 系统自带:89MB

7z mx=9 那 1.2GB 峰值,在 16GB 的台机上无所谓,在只有 1GB、2GB 内存的软路由、老 NAS、电视盒子上就是直接把机器顶死。这也是我给小主机推荐 zip 而不是 7z 的原因,跟压缩率无关,纯粹是内存。

码流那 258MB,压完一分钱没省

目录 B,258MB,其中 256MB 是已经压过一遍的码流:

  • 7z mx=5 固实:35.8 秒,257.41MB,峰值内存 1198MB
  • zip mx=5:20.7 秒,257.40MB
  • zip mx=1:16.0 秒,257.40MB
  • bsdtar:15.1 秒,257.48MB

四个结果体积几乎一模一样,比率 1.00x。H.264、HEVC 的码流和 JPEG 一样,熵已经被榨干了,任何通用压缩算法都找不到可压的冗余,只能原样存。

但时间白花了 15 到 36 秒,7z 还额外吃了 1.2GB 内存。这就是「把整季剧打个包存起来」这件事的真相:真正被压缩的只有字幕、nfo、海报那几 MB,正片那部分你只是让 CPU 把 256MB 读一遍、写一遍。

想让 CPU 别白跑,用 store 模式(zip 的 -mx=0),几十毫秒就过完,体积一分不差。

中文名:三个工具写进去的东西完全不一样

这段是这次最值得记的。zip 的文件名没有强制编码,靠两样东西约定:通用标志位第 11 位(UTF-8 标志),和扩展字段。我把同一组中文名——「第一集 字幕.srt」「海报 终版.jpg」「说明.txt」——分别压了四遍,然后直接读 zip 的中央目录看字节:

  • 7-Zip 25.01 命令行默认:名字写成 GBK 字节(b5 da d2 bb …),UTF-8 标志位是 0,主机标识写 DOS,但额外塞了一个 0x7075 Unicode Path 扩展字段,里面存的是 UTF-8 名。会读这个字段的工具(新版 7-Zip、Python 3.13)能还原,只按 UTF-8 猜名字的工具就乱。
  • 7-Zip 加 -mcu=on:名字是 UTF-8 字节,标志位 1,干净利落。
  • 系统自带 Compress-Archive:UTF-8 字节加标志位 1,不依赖任何扩展字段,是最规范的一档。
  • Windows 自带的 tar.exe(bsdtar 3.8.9):名字是 GBK 字节、标志位 0、没有 0x7075,可主机标识偏偏写成了 Unix(3)。

最后这个组合最要命。我用 7za 去解 bsdtar 打的包,解出来的文件名是「˵.txt」这种残字——字节和声明互相矛盾,工具只能二选一,选哪个都错。看起来是 7-Zip 见主机标识是 Unix,就按 UTF-8 去读名字,而字节其实是 GBK。

对比一下就很清楚:

  • 同一个 GBK 字节、带 0x7075 兜底的包,7za 解出来三个中文名全部正常
  • 系统自带压缩的包,7za 解出来也正常
  • bsdtar 那个包,7za 解出来名字全烂

所以「压缩包乱码」不是玄学,是三个字段有没有对齐的问题。比较稳的做法只有三条:给跨平台的人传,要么用系统自带压缩(最规范),要么 7z 加 -mcu=on,要么直接用 7z 格式——7z 容器内部强制 UTF-16 存名字,没有这段历史包袱。

我现在的用法

  • 传给 Mac、Linux、手机用户:7z 格式,或者 zip 加 -mcu=on
  • 只在自己 Windows 上备份、自己解:zip -mx=5,21 秒、56MB、80MB 内存,别碰 -mx=9
  • 小内存的软路由、老 NAS、电视盒子:用 zip,不要 7z 的高档位,1.2GB 峰值真的会顶死
  • 归档整季剧:把字幕、nfo、海报单独打一包,正片原样放着,整包压只是让 CPU 白跑
  • 系统自带的右键压缩:急用可以,但不值得当默认,慢且体积大

你们往 NAS 上归档片子的时候,是整包压一遍,还是像我这样只压字幕那一层?

回复

还没有回复,抢个沙发

登录后即可参与讨论

去登录 注册账号

相关帖子