gzip:解释解压缩的位

时间:2012-12-03 06:34:23

标签: java gzip inflate

我正在尝试通过在Java中实现它来学习Inflate算法,以便我可以在汇编中为具有非常有限的指令集的CPU实现它。

在读取文字,距离和长度代码的数量后,我无法从文件中读取正确的代码长度。 我正在按照here所述的实现进行操作,其中提供了一个示例.gz文件gunzip.c.gz。在读取gzip头文件后,以下是第一个56位(如果我正确读取它),压缩数据块:

10111101 00011011 11111101 01101111 11011010 11001000 11110010

我将通过以下偏移来引用字节中的位:[76543210] 第一个字节10111101包含偏移end of block的{​​{1}},偏移0包含确定块类型的两个位。
在这种情况下,这是最后一个块,它是一个动态的霍夫曼树。

要解释的以下位是文字(5位),距离(5位)和长度(4位)代码的数量。阅读内容如下:

21

在此之后,我遇到了麻烦。接下来的36位应该是12组3位,表示代码长度 从上面的字节,我看到(解释为little-endian):

10111101 -> 10111XXX -> 23 (literal)
00011011 -> XXX11011 -> 27 (distance)
00011011 11111101 -> 000XXXXX XXXXXXX1 -> 1000 -> 8 (length)

但我希望(如上面的链接所示)

110 111 111 011 011 010 011 011 100 100 101 100
3   7   7   6   6   2   6   6   1   1   5   1

我看不到从文件中获取这些值的任何方法。我必须误解应该如何读取这些位。给定一个具有5位值后跟3位值的字节101 011 011 110 110 110 110 110 110 001 001 001 5 6 6 3 3 3 3 3 3 4 4 4 ,我会将其读作[CBA43210]01234

这篇文章的正确代码长度应该是错误的,或者更可能的是,我对它们应该如何解释是错误的?

1 个答案:

答案 0 :(得分:1)

  

位本身被读取LSB到MSB,如图6所示:

<----
87654321

(来自问题链接的文件)表示

  

[CBA43210]我会把它读作01234和ABC。

(来自问题本身)是正确的。

Little-endian表示首先存储或读取(此处,解释)最低有效位(此处为位)。

但是,01234ABC本身属于小端,因此字节110 11000将被解释为3 3,而不是24 6

这意味着

中的五位,五位和四位
10111101 00011011 ...

xxx11101 => 11101  => 29
101xxxxx
xxxxxx11 => 11 101 => 29
xx0110xx => 0110   => 6