Deflate压缩块的结构

Eug*_*Zol 4 unix assembly gzip bit-manipulation deflate

理解Deflate算法(RFC 1951)时遇到了麻烦.

TL; DR如何解析Deflate压缩块4be4 0200

我创建了一个带有字母和换行符的文件a\n,然后运行gzip a.txt.结果文件a.txt.gz:

1f8b 0808 fe8b eb55 0003 612e 7478 7400

4be4 0200

07a1 eadd 0200 0000
Run Code Online (Sandbox Code Playgroud)

我知道第一行是带有附加信息的标题,最后一行是CRC32加上输入大小(RFC 1951).这两个给我带来了麻烦.

但是我如何解释压缩块本身(中间线)?

这是它的十六进制和二进制表示:

4be4 0200

0100 1011
1110 0100
0000 0010
0000 0000
Run Code Online (Sandbox Code Playgroud)

据我了解,不知何故这些:

每个压缩数据块都以3个包含以下数据的标头位开头:

  • 第一位BFINAL
  • 接下来的2位BTYPE

......实际上是在第一个字节结束时结束:0100 1 011.(我将跳过这个问题,为什么有人会称之为"标题"的东西实际上是其他东西的尾巴.)

RFC包含的东西,据我所知,应该是对此的解释:

  • 数据元素按字节中的位数增加的顺序打包成字节,即从字节的最低有效位开始.
  • 除了霍夫曼码之外的数据元素从数据元素的最低有效位开始打包.
  • 霍夫曼代码从代码的最高位开始打包.

换句话说,如果要将压缩数据打印出来作为一个字节序列,从右边距的第一个字节开始, 然后向左移动,左边每个字节的最重要位像往常一样,将能够从右到左解析结果,其中固定宽度元素在正确的MSB到LSB顺序中,而霍夫曼代码以位反转顺序(即,相对LSB位置中的代码的第一位) .

但遗憾的是我不明白这个解释.

回到我的数据.好的,所以设置了BFINAL,而BTYPE是什么?10或01?

如何解释该压缩块中的其余数据?

Ros*_*dge 10

首先让我们将压缩数据的十六进制表示看作一系列字节(而不是你问题中的一系列16位大端值):

4b e4 02 00
Run Code Online (Sandbox Code Playgroud)

现在让我们将这些十六进制字节转换为二进制:

01001011 11100100 00000010 000000000
Run Code Online (Sandbox Code Playgroud)

根据RFC,这些位被打包为"从字节的最低有效位开始".字节的最低有效位是字节的最左位.所以第一个字节的第一位就是这个:

01001011 11100100 00000010 000000000
       ^
       first bit
Run Code Online (Sandbox Code Playgroud)

第二位是这一个:

01001011 11100100 00000010 000000000
      ^
      second bit
Run Code Online (Sandbox Code Playgroud)

第三位:

01001011 11100100 00000010 000000000
     ^
     third bit
Run Code Online (Sandbox Code Playgroud)

等等.一旦遍历了第一个字节中的所有位,就可以从第二个字节的最低有效位开始.所以第九位是这一个:

01001011 11100100 00000010 000000000
                ^
                ninth bit
Run Code Online (Sandbox Code Playgroud)

最后,最后一位,第三十二位,就是这一位:

01001011 11100100 00000010 000000000
                           ^
                           last bit
Run Code Online (Sandbox Code Playgroud)

BFINAL值是压缩数据中的第一位,因此包含在上面标记为"第一位"的单个位中.它的值为1,表示这是压缩数据中的最后一个块.

BTYPE值存储在数据的后两位中.这些是上面标记为"第二位"和"第三位"的位.唯一的问题是两者中哪一位是最低有效位,哪一位是最重要的位.根据RFC,"除了霍夫曼代码之外的数据元素从数据元素的最低有效位开始打包." 这意味着这两个位中的第一位,即标记为"第二位"的位,是最不重要的位.这意味着BTYPE的值是01二进制的.因此表示使用固定的霍夫曼码压缩块.

这就是容易完成的部分.解码压缩块的其余部分更加困难(并且使用更现实的示例,更加困难).正确地解释这将如何使这个答案太久(并且你的问题太广泛)对于这个网站.我会给你一个提示,数据中接下来的三个元素是霍夫曼代码10010001('a'),00111010('\n')和0000000(流结束).其余6位未使用,不属于压缩数据.

请注意,要了解如何解压缩压缩数据,您必须了解Huffman代码是什么.您所遵循的RFC假设您这样做.您还应该知道LZ77压缩是如何工作的,尽管文档或多或少地解释了您需要知道的内容.

  • @EugZol 这取决于你如何看待事物。标头位从数据的第一位开始。数据的第一位是第一个字节的第一位。字节中的位按最低有效位在前,最高有效位在后进行排序。这与我们通常对数字的排序方式相同,最不值的数字在前,最值的数字在后。问题是我们把数字的数字倒着写,我们把数字的最高有效数字放在最前面,把最低有效数字放在最后。如果我们尝试从左到右读取二进制数字,这会翻转二进制数字的顺序。 (2认同)
  • @EugZol 无论您如何看待事物,都不应该使提取这些位变得更加困难。在 C 中你会做一些类似 `bit = byte & 1; 的事情。字节 >>= 1;`。如果这些位是按照您预期的方式提取的,首先是字节的最右边和最重要的位,那么您将不得不执行类似 `bit = (byte >> 7) & 1; 的操作。字节 <<= 1;` 代替。 (2认同)