【问题标题】:How to manually construct a gzip so that compressed file is larger than original?如何手动构建 gzip 以使压缩文件大于原始文件?
【发布时间】:2025-07-06 06:10:01
【问题描述】:

假设有一个 1KB 的文件名为 data.bin,如果可以构造一个 gzip 的 data.bin.gz,但要大得多,怎么办?

理论上,GZIP 格式可以扩大多少?

【问题讨论】:

  • 好吧,我想听听为什么这不是编程,**** 人们想结束这个问题。
  • 我不知道。对我来说看起来像是一个编程问题:-)
  • 我认为这里的主要思想是,如果信息是“可压缩的”(有重复的模式可以用占用更少空间来存储的东西代替),那么你可以压缩,否则, zip 文件只会增加开销,将元数据添加到无法压缩的内容中。例如:有人试图压缩一个压缩文件。
  • @est 关闭!关闭一切!更多闭包之神!哇!

标签: gzip huffman-code data-compression


【解决方案1】:

您可以将其设置为任意大。获取任何 gzip 文件并在以下五个字节中插入任意数量的重复项:00 00 00 ff ff 在 gzip 标头之后和 deflate 数据之前。

【讨论】:

  • 哈哈,很好地利用了 GZIP 格式。但是我们可以直接用霍夫曼表和压缩算法做任何事情吗?
  • 具体来说是对deflate压缩数据格式的“利用”。
  • 您可能没有匹配项,并安排所有使用的字节值的霍夫曼代码长度为 15 位(假设只使用了一些字节值)。然后,包括标题,结果将是未压缩数据大小的两倍多。我不认为你可以在不插入空或几乎空的放气块的情况下让它更大,就像我的回答一样。例如,您可以对每个 deflate 块只编码一个字节,每个块有一百或更多字节的开销。但是,这与仅插入空块没有太大区别。
【解决方案2】:

总结:

  • 带有标题字段/一般结构:效果不受限制,除非遇到软件限制
  • 空块:格式规范的无限影响
  • 未压缩块:效果限制为 6x
  • 压缩块:通过明显的手段,最大效果估计为 1.125 倍,很难实现

采用 gzip 格式(RFC1952(元数据)、RFC1951(放气格式)、additional notes for GNU gzip),随心所欲地使用它。

标题

有很多地方可以利用:

  • 使用可选字段(原始文件名、文件注释、额外字段)
  • 直接追加垃圾(GNU gzip解压时会发出警告)
  • 连接多个 gzip 存档(格式允许,生成的未压缩数据同样是连接或所有块)。
    • 一个有趣的副作用(显然是 GNU gzip 中的一个错误):gzip -l 仅从最后一个块中获取报告的未压缩大小(即使它是垃圾),而不是将所有值相加。因此,您可以使其看起来看起来像存档比原始数据(荒谬地)更大/更小。

这些是立即显而易见的,您也许可以找到其他方法。

数据

“deflate”格式的一般布局是(RFC1951):

一个压缩数据集由一系列块组成,对应于 输入数据的连续块。块大小是任意的, 除了不可压缩块限制为 65,535 字节。
<...>
每个块由两部分组成:一对霍夫曼代码树 描述压缩数据部分的表示,以及 压缩数据部分。 (霍夫曼树本身是压缩的 使用霍夫曼编码。)压缩数据由一系列 两种类型的元素:文字字节(尚未被 检测为在前 32K 输入字节中重复),以及 指向重复字符串的指针,其中指针表示为 对。中使用的表示 “deflate”格式将距离限制为 32K 字节,长度限制为 258 字节,但不限制块的大小,除了 不可压缩的块,如上所述受到限制。

完整块

00 00 00 ff ffMark Adler suggests 本质上是一个空的非最终块(RFC1951 第 3.2.3. 节用于第一个字节,3.2.4. 用于未压缩块本身)。
顺便说一句,根据gzip overview at the official site和源码,Mark是解压部分的作者……

未压缩块

使用非空的未压缩块(参见前面的参考部分),您最多可以为每个符号创建一个。因此效果被限制在 6 倍。

压缩块

简而言之:一些通货膨胀是可以实现的,但它非常困难,可实现的效果是有限的。除非你有充分的理由,否则不要在他们身上浪费时间。

在压缩块内(第 3.2.5 节),每个块都是 [&lt;encoded character(8-9 bits&gt;|&lt;encoded chunk length (7-11 bits)&gt;&lt;distance back to data(5-18 bits)&gt;],长度从 3 开始。7-9 位代码明确地解析为文字字符或特定长度范围。较长的代码对应于较大的长度/距离。块之间不允许有空格/无意义的东西。
因此,原始字节块的最大值为 9/8 (1.125x) - 如果 all 原始字节的代码为 144 - 255。
使用引用块对您没有任何好处:即使是对 3 字节序列的引用也最多只能得到 25/24 (1.04x)。

静态霍夫曼表就是这样。查看有关动态文档的文档,它针对特定数据或其他内容优化了上述编码。因此,它应该允许使给定数据的比率更接近可实现的最大值,但仅此而已。

【讨论】: