如何手动构建gzip以使压缩文件大于原始文件?

时间:2016-05-31 02:23:27

标签: gzip huffman-code data-compression

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

我们理论上可以用GZIP格式获得多大的数据?

2 个答案:

答案 0 :(得分:2)

你可以任意大。获取任何gzip文件,并在gzip标头之后和deflate数据之前插入五个字节的任意数量的重复:00 00 00 ff ff

答案 1 :(得分:1)

要点:

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

采用gzip格式(RFC1952(元数据),RFC1951(deflate格式),additional notes for GNU gzip)并尽可能多地使用它。

标题

有很多地方可以利用:

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

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

数据

“deflate”格式的总体布局是(RFC1951):

  

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

完整区块

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

未压缩块

使用非空的未压缩块(参见上一节参考),您最多可以为每个符号创建一个。因此效果限于6倍。

压缩块

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

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

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