压缩解压缩工具
在线 Zlib、Gzip、Deflate、Brotli 压缩与解压缩工具。文本可压缩为 Hex 或 Base64,浏览器本地处理,数据不上传服务器。
描述:
压缩不是“越小越好”:四种无损算法各有封装成本
Zlib、Gzip、Deflate 与 Brotli 都是无损压缩算法,解压后能逐字节还原原始数据,不会丢失任何信息。它们的核心都基于 Deflate(LZ77 + Huffman),但封装格式与适用场景并不相同。一个常被忽略的事实是:压缩率不只取决于算法,还取决于输入本身的冗余度与封装带来的固定开销——对极短的文本,Gzip 的 18 字节头尾开销反而会让结果比原文更长。下文本着“用实测数字说话”的思路,把四种算法的规格、级别权衡、可压缩性规律与默认输入的真实输出逐一拆解。除特殊说明外,所有数字均由与本工具同源的压缩算法(Node zlib,对应 fflate 的 Deflate/Zlib、Node 的 Gzip、Brotli)逐项算出。
表 1:四种算法的规格与封装对照
| 算法 | 标准 | 内核 | 封装开销(相对裸 Deflate 的固定字节) | 校验方式 | 典型用途 |
|---|---|---|---|---|---|
| Deflate | RFC 1951 | LZ77 + Huffman | 0 字节(裸流,无头无尾) | 无 | 作为 Zlib / Gzip 的内核,用于内部传输 |
| Zlib | RFC 1950 | Deflate | +6 字节(2 字节头 + 4 字节 Adler-32 尾) | Adler-32 | HTTP 压缩、PNG、Git 对象 |
| Gzip | RFC 1952 | Deflate | +18 字节(10 字节文件头 + 8 字节 CRC-32 / ISIZE 尾) | CRC-32 | .gz 文件、服务器响应压缩 |
| Brotli | RFC 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) |
|---|---|---|---|---|---|---|
| 1 | 1799 | 86.2% | 6 | 1647 | 87.4% | 2 |
| 2 | 1777 | 86.4% | 2 | 1478 | 88.7% | 9 |
| 3 | 1739 | 86.7% | 3 | 1422 | 89.1% | 10 |
| 4 | 1744 | 86.6% | 4 | 1364 | 89.5% | 21 |
| 5 | 1706 | 86.9% | 4 | 1169 | 91.0% | 24 |
| 6 | 1706 | 86.9% | 5 | 1169 | 91.0% | 45 |
| 7 | 1692 | 87.0% | 5 | 1148 | 91.2% | 98 |
| 8 | 1692 | 87.0% | 6 | 1148 | 91.2% | 102 |
| 9 | 1692 | 87.0% | 6 | 1143 | 91.2% | 129 |
| 10 | — | — | — | 1118 | 91.4% | 218 |
| 11 | — | — | — | 1070 | 91.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 后字节 | 节省比例 | 规律说明 |
|---|---|---|---|---|
| 中文散文 | 1260 | 244 | 80.6% | UTF-8 每字 3 字节且冗余高,可压空间大 |
| HTML 页面 | 2027 | 514 | 74.6% | 标签大量重复,压缩率中高 |
| JSON 配置 | 5561 | 772 | 86.1% | 键名反复出现,压缩率很高 |
| 服务器日志 | 4200 | 175 | 95.8% | 行格式高度一致,压缩率极高 |
| 已压缩数据(模拟 JPEG / MP3) | 20000 | 20028 | -0.1% | 本身已压缩,再压几乎无效甚至微增 |
| Base64 文本 | 26668 | 20118 | 24.6% | 编码已消除大部分冗余,剩余可压空间小 |
业界经验上,自然英文散文经 Gzip 通常能压到原文的 20%–30%(即节省 70%–80%),与表中中文散文 80.6% 的结果同向;JPEG、MP3、ZIP 等已压缩数据再压基本没有收益。关于“先清理文本还是先压缩”的更多实践,可参考博客 文本清理指南。
表 4:用页面默认输入实测——四种算法压缩前后对照
下表严格使用本工具默认的演示文本(223 字节)与页面输出口径(压缩体积含各自封装,节省 = 1 − 压缩字节 / 原始字节),并附上“再转成 Base64 / Hex”的文本化长度:
| 算法 | 原始字节 | 压缩后字节 | 节省 | Base64 长度 | Hex 长度 |
|---|---|---|---|---|---|
| Gzip(默认) | 223 | 231 | -3.6% | 308 | 462 |
| Zlib | 223 | 219 | 1.8% | 292 | 438 |
| Deflate | 223 | 213 | 4.5% | 284 | 426 |
| Brotli | 223 | 179 | 19.7% | 240 | 358 |
注意:默认演示文本很短,用 Gzip 会得到 231 字节(比原文还长 3.6%)——这正是表 1 里 18 字节头尾开销盖过了可压冗余的结果。同一段短文本,换成无头的 Deflate 转为正收益(213 字节),Brotli 更是压到 179 字节。这说明短文本不必迷信 Gzip,选 Deflate 或 Brotli 更划算;只有当文本足够长、足够冗余时,Gzip 才稳赚。
表 5:Base64 / Hex 编码的膨胀,以及“先 Base64 再压缩”的净效果
压缩结果是二进制,要放进文本环境就必须编码。以默认输入经 Gzip 得到的 231 字节为例,两种文本化编码的长度如下:
| 编码方式 | 长度 | 相对压缩结果的膨胀 |
|---|---|---|
| 二进制(原始) | 231 字节 | 1.00× |
| Base64 | 308 字符 | 1.33× |
| Hex | 462 字符 | 2.00× |
Base64 把体积变为 4/3,Hex 变为 2 倍,这是编码的固有代价。另一个常见误区是“先把数据 Base64 一遍再压缩会更小”,实测并非如此。仍用默认输入(223 字节):
| 处理步骤 | 体积 | 说明 |
|---|---|---|
| 原文 | 223 字节 | 起点 |
| 先 Base64 编码 | 300 字节 | 膨胀 +34.5% |
| 再 Gzip | 240 字节 | 只能回收一小部分膨胀 |
| 直接 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 令牌 | 对应算法 | 标准 | 现状说明 |
|---|---|---|---|
| gzip | Gzip | RFC 1952 | 服务器最广泛支持,兼容性最佳 |
| deflate | Deflate | RFC 1951 | 历史上浏览器实现多为 zlib 封装,故单独使用较少 |
| br | Brotli | RFC 7932 | 静态资源(CSS/JS/字体/HTML)首选,同体积更小 |
| zstd | Zstandard | RFC 8878 | 较新算法,部分 CDN 已支持(本工具未实现,仅作对照) |
| identity | 不压缩 | RFC 9110 | 默认/占位,表示无编码 |
| compress | UNIX 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)。本工具可在本地离线验证这两种编码的产物,不必每次都上线抓包。