压缩解压缩工具

在线 Zlib、Gzip、Deflate、Brotli 压缩与解压缩工具。文本可压缩为 Hex 或 Base64,浏览器本地处理,数据不上传服务器。

压缩 解压缩
Zlib Gzip Deflate Brotli
Ctrl/⌘ + Enter 运行
处理错误

描述:

压缩不是“越小越好”:四种无损算法各有封装成本

Zlib、Gzip、Deflate 与 Brotli 都是无损压缩算法,解压后能逐字节还原原始数据,不会丢失任何信息。它们的核心都基于 Deflate(LZ77 + Huffman),但封装格式与适用场景并不相同。一个常被忽略的事实是:压缩率不只取决于算法,还取决于输入本身的冗余度与封装带来的固定开销——对极短的文本,Gzip 的 18 字节头尾开销反而会让结果比原文更长。下文本着“用实测数字说话”的思路,把四种算法的规格、级别权衡、可压缩性规律与默认输入的真实输出逐一拆解。除特殊说明外,所有数字均由与本工具同源的压缩算法(Node zlib,对应 fflate 的 Deflate/Zlib、Node 的 Gzip、Brotli)逐项算出。

表 1:四种算法的规格与封装对照

算法标准内核封装开销(相对裸 Deflate 的固定字节)校验方式典型用途
DeflateRFC 1951LZ77 + Huffman0 字节(裸流,无头无尾)无作为 Zlib / Gzip 的内核,用于内部传输
ZlibRFC 1950Deflate+6 字节(2 字节头 + 4 字节 Adler-32 尾)Adler-32HTTP 压缩、PNG、Git 对象
GzipRFC 1952Deflate+18 字节(10 字节文件头 + 8 字节 CRC-32 / ISIZE 尾)CRC-32.gz 文件、服务器响应压缩
BrotliRFC 7932上下文建模 + LZ77 + Huffman流头 1–2 字节(含窗口位 WBITS)+ 结尾 ISLAST 标记;无独立校验字段依赖传输层Web 字体、静态资源(Content-Encoding: br)

表中“封装开销”已用本工具算法逐项实测验证:对同一输入,Zlib 输出恰好比裸 Deflate 多 6 字节、Gzip 多 18 字节,与 RFC 规定的封装长度完全一致。Brotli 因算法更优,常比裸 Deflate 还小,故不以“固定开销”衡量,而直接看压缩体积。需要先把网页里的标签去掉、得到纯文本再压,可配合 HTML 标签剥离工具;压缩前想估算原文规模,可用 字数统计工具 先看字节数。

表 2:压缩级别 1–9(Brotli 至 11)的体积与耗时权衡

级别只影响“压缩时愿意花多少力气”:级别越高,体积略小、但耗时明显上升。以下以约 13 KB 的 HTML/CSS/JSON 混合样例(含合理重复结构,非极端压测)实测,Gzip 取 1–9 级、Brotli 取 1–11 级,体积与节省比例为确定值,耗时为同一参考机器的多次测量中位数(仅供相对比较):

级别Gzip 体积(字节)Gzip 节省Gzip 耗时(ms/MB)Brotli 体积(字节)Brotli 节省Brotli 耗时(ms/MB)
1179986.2%6164787.4%2
2177786.4%2147888.7%9
3173986.7%3142289.1%10
4174486.6%4136489.5%21
5170686.9%4116991.0%24
6170686.9%5116991.0%45
7169287.0%5114891.2%98
8169287.0%6114891.2%102
9169287.0%6114391.2%129
10———111891.4%218
11———107091.8%576

注意:耗时数字随设备与输入波动,仅用于体现“相对快慢”的趋势。结论很清晰:Gzip 1–9 级的体积几乎不变(都在 1692–1799 字节区间),耗时也始终很低;而 Brotli 从 1 级到 11 级体积仅再降约 4 个百分点,耗时却从约 2 ms/MB 飙升到约 576 ms/MB(约 300 倍)。因此网页静态资源常用 Brotli 级别 5–6 作为性价比拐点,再往上基本是“用时间换几乎不变的字节”。与压缩结果的文本化编码一样,URL 编码 也是为了在纯文本环境里安全搬运二进制而存在的编码手段。

表 3:不同文本类型的可压缩性规律

压缩算法对“重复多、冗余高”的文本最有效,对已经压缩过或随机的数据几乎无效。下表用本工具对六类典型输入做 Gzip 实测(样例规模见“原始字节”列):

文本类型原始字节Gzip 后字节节省比例规律说明
中文散文126024480.6%UTF-8 每字 3 字节且冗余高,可压空间大
HTML 页面202751474.6%标签大量重复,压缩率中高
JSON 配置556177286.1%键名反复出现,压缩率很高
服务器日志420017595.8%行格式高度一致,压缩率极高
已压缩数据(模拟 JPEG / MP3)2000020028-0.1%本身已压缩,再压几乎无效甚至微增
Base64 文本266682011824.6%编码已消除大部分冗余,剩余可压空间小

业界经验上,自然英文散文经 Gzip 通常能压到原文的 20%–30%(即节省 70%–80%),与表中中文散文 80.6% 的结果同向;JPEG、MP3、ZIP 等已压缩数据再压基本没有收益。关于“先清理文本还是先压缩”的更多实践,可参考博客 文本清理指南。

表 4:用页面默认输入实测——四种算法压缩前后对照

下表严格使用本工具默认的演示文本(223 字节)与页面输出口径(压缩体积含各自封装,节省 = 1 − 压缩字节 / 原始字节),并附上“再转成 Base64 / Hex”的文本化长度:

算法原始字节压缩后字节节省Base64 长度Hex 长度
Gzip(默认)223231-3.6%308462
Zlib2232191.8%292438
Deflate2232134.5%284426
Brotli22317919.7%240358

注意:默认演示文本很短,用 Gzip 会得到 231 字节(比原文还长 3.6%)——这正是表 1 里 18 字节头尾开销盖过了可压冗余的结果。同一段短文本,换成无头的 Deflate 转为正收益(213 字节),Brotli 更是压到 179 字节。这说明短文本不必迷信 Gzip,选 Deflate 或 Brotli 更划算;只有当文本足够长、足够冗余时,Gzip 才稳赚。

表 5:Base64 / Hex 编码的膨胀,以及“先 Base64 再压缩”的净效果

压缩结果是二进制,要放进文本环境就必须编码。以默认输入经 Gzip 得到的 231 字节为例,两种文本化编码的长度如下:

编码方式长度相对压缩结果的膨胀
二进制(原始)231 字节1.00×
Base64308 字符1.33×
Hex462 字符2.00×

Base64 把体积变为 4/3,Hex 变为 2 倍,这是编码的固有代价。另一个常见误区是“先把数据 Base64 一遍再压缩会更小”,实测并非如此。仍用默认输入(223 字节):

处理步骤体积说明
原文223 字节起点
先 Base64 编码300 字节膨胀 +34.5%
再 Gzip240 字节只能回收一小部分膨胀
直接 Gzip 原文231 字节对照基准

注意:“先 Base64 再 Gzip”得到 240 字节,比“直接 Gzip”的 231 字节反而多 9 字节,净节省为 −7.6%。Base64 的 33% 膨胀无法被后续压缩完全抵消,所以正确顺序永远是“先压缩、再 Base64”,绝不要反过来。

表 6:HTTP 传输层的 Content-Encoding 节省(RFC 9110)

在网络传输中,压缩通过 Content-Encoding 响应头声明,客户端用 Accept-Encoding 协商,规则见 HTTP 语义标准 RFC 9110(2022 年发布,替代 RFC 7231)。本工具模拟的正是这些编码的产物,便于本地离线验证服务端结果:

Content-Encoding 令牌对应算法标准现状说明
gzipGzipRFC 1952服务器最广泛支持,兼容性最佳
deflateDeflateRFC 1951历史上浏览器实现多为 zlib 封装,故单独使用较少
brBrotliRFC 7932静态资源(CSS/JS/字体/HTML)首选,同体积更小
zstdZstandardRFC 8878较新算法,部分 CDN 已支持(本工具未实现,仅作对照)
identity不压缩RFC 9110默认/占位,表示无编码
compressUNIX compress (LZW)历史已淘汰,几乎不再使用

值得一提的是 Zstandard(Zstd,RFC 8878,由 Facebook 于 2015 年发布):它的压缩率与速度曲线介于 Gzip 与 Brotli 之间,且解压极快,正被越来越多 CDN 接纳;但它不在本工具的四种模式之内,上表仅作算法谱系对照。国内主流 CDN(如阿里云 CDN、腾讯云 CDN)默认开启的也正是 Gzip 与 Brotli(br)两种,与 RFC 9110 的协商机制一致。

三个真实算例(与页面默认参数自洽)

以下三个算例均使用本工具默认的演示文本(223 字节)与默认编码格式(Base64),仅切换算法或处理顺序,数字与上面各表完全一致。

算例 1:短文本用 Gzip 反而变大

默认文本(223 字节)保持 Gzip + Base64 直接点“执行”:Gzip 得 231 字节(节省 −3.6%,因 18 字节头尾开销盖过可压冗余)→ Base64 后 308 字符。这说明短文本用 Gzip 可能得不偿失,应改用 Deflate 或 Brotli。

算例 2:同一短文本,Brotli 仍能压住

同样 223 字节默认文本,切到 Brotli(页面默认级别 6):得 179 字节(节省 19.7%)→ Base64 后 240 字符。同样的短文本,Brotli 凭借更激进的上下文建模仍有效,比 Gzip 少 52 字节。

算例 3:Base64 膨胀后再压缩的净效果

默认文本 223 字节 → 先 Base64 得 300 字节(+34.5%)→ 再 Gzip 得 240 字节;而直接 Gzip 原文仅 231 字节。先 Base64 再压缩(240 字节)比直接压缩(231 字节)多 9 字节,净节省 −7.6%。结论:传输前若必须文本化,务必先压缩再 Base64,而非相反。

补充问答

为什么对很短的文本身压缩,Gzip 结果反而比原文长?

因为 Gzip 固定写入 10 字节文件头 + 8 字节 CRC/长度尾,共 18 字节。若原文很小、冗余又少,这 18 字节开销比被压掉的内容还多,就出现“越压越大”。本工具默认输入框(223 字节)实测 Gzip 得 231 字节(−3.6%)。改用无头的 Deflate 或更强的 Brotli 即可转为正收益。

Zlib 和 Gzip 都用 Deflate 内核,压缩体积为什么不同?

二者压缩“正文”的算法完全相同,差异只在封装。Zlib 在 Deflate 外加 2 字节头 + 4 字节 Adler-32(共 6 字节),Gzip 外加 10 字节头 + 8 字节尾(共 18 字节)。对本工具同一输入实测:Zlib 比裸 Deflate 多 6 字节、Gzip 多 18 字节,与 RFC 规定一致。所以同样的正文,Gzip 永远比 Zlib 大 12 字节。

已经用 Base64 编码过的数据,再压缩还有意义吗?净效果如何?

意义有限且常常得不偿失。Base64 先把体积膨胀约 33%(每 3 字节变 4 字节),后续 Gzip 只能回收其中一小部分。以本工具默认文本为例:原文 223 字节 → Base64 300 字节 → 再 Gzip 240 字节,反而比直接 Gzip 原文的 231 字节还多 9 字节。正确顺序是“先压缩、再 Base64”。

网页传输时 Content-Encoding 该选 gzip 还是 br?

静态资源(CSS/JS/字体/HTML)优先 Brotli(br),相同体积下通常比 Gzip 更小、解码也快;动态接口或需兼容老旧客户端时退回 Gzip。两者都依赖客户端在 Accept-Encoding 中声明支持,由服务端按 RFC 9110 协商(见上表 6)。本工具可在本地离线验证这两种编码的产物,不必每次都上线抓包。