zlib头部长什么样?

95
在我的项目中,我需要了解 zlib 标头是什么样子的。我听说它相当简单,但我找不到关于 zlib 标头的任何描述。
例如,它是否包含一个魔数?
6个回答

144

zlib魔术标头

78 01 - No Compression/low
78 9C - Default Compression
78 DA - Best Compression 

2
这帮助我弄清楚了我正在处理的压缩类型。我知道文件已经被压缩,但一直在搜索一些头字节,然后这个出现了。谢谢! - ProVega
5
使用Java Inflator(使用ZLIB)时,我看到头部值为120、-100。这相当于78 9C。这证实了您上面所说的内容。 - Dan
2
这只是64个可能的zlib头文件中的三个。请参考mwfearnley的回答。 - Mark Adler
3
有四个可能的 78 答案 - 这个答案省略了 78 5E - 它落在无/默认之间。另外还有28个值不太可能被看到,但仍然有效。 - mwfearnley

104

链接到RFC

0   1
+---+---+
|CMF|FLG|
+---+---+

CMF(压缩方法和标志) 该字节按照压缩方法分为4位和依赖于压缩方法的4位信息字段。

bits 0 to 3  CM     Compression method
bits 4 to 7  CINFO  Compression info

压缩方法CM (Compression method) 该字段标识文件中所使用的压缩方法。当CM = 8时,表示使用了最大为32K的“deflate”压缩方法,包括gzip和PNG等几乎所有其他文件格式都使用此方法。而CM = 15则保留。

压缩信息CINFO (Compression info) 对于CM = 8,CINFO是LZ77窗口大小以2为底的对数减去8(CINFO=7表示32K窗口大小)。本版本规范中不允许CINFO大于7的值。对于CM不等于8的情况,本规范未定义CINFO。

实际上,这意味着第一个字节几乎总是78(十六进制)

标志FLG (FLaGs) 该标志字节分成以下部分:

bits 0 to 4  FCHECK  (check bits for CMF and FLG)
bit  5       FDICT   (preset dictionary)
bits 6 to 7  FLEVEL  (compression level)

FCHECK的值必须满足以下条件:当将CMF和FLG表示为以MSB顺序存储的16位无符号整数(即CMF * 256 + FLG),其值必须是31的倍数。

FLEVEL (压缩级别) 这些标志仅供特定压缩方法使用。 "deflate"方法 (CM = 8) 设置以下标志:

        0 - compressor used fastest algorithm
        1 - compressor used fast algorithm
        2 - compressor used default algorithm
        3 - compressor used maximum compression, slowest algorithm

这是一个很棒的答案:),在许多方面帮助了我...嘿!漂亮的头像。 - Ryan
2
好的,所以这里的较低位数指的是不太重要的位,而不是 MSB。当你说“位#0”时,我感到非常困惑。 - Константин Ван

30

ZLIB/GZIP 头部

Level | ZLIB  | GZIP 
  1   | 78 01 | 1F 8B 
  2   | 78 5E | 1F 8B 
  3   | 78 5E | 1F 8B 
  4   | 78 5E | 1F 8B 
  5   | 78 5E | 1F 8B 
  6   | 78 9C | 1F 8B 
  7   | 78 DA | 1F 8B 
  8   | 78 DA | 1F 8B 
  9   | 78 DA | 1F 8B 

Deflate没有常见的头部信息。


4
gzip流的前三个字节是固定的:1f 8b 08,这样可以更好地区分。此外,您只展示了64个可能的zlib头文件中的四个。请参阅mwfearnley的回答。 - Mark Adler

28

ZLIB头(如RFC1950所定义的)是一个16位的大端值,换句话说,它由两个字节组成,第一个字节包含高位,第二个字节包含低位。

从最重要到最不重要它包含以下比特域:


  • CINFO(位于第一个字节的12-15位)
    以2的幂表示窗口大小,范围从0(256字节)到7(32768字节),通常为7。不允许使用更高的值。

  • CM(位于第一个字节的8-11位)
    压缩方法。只允许使用Deflate(8)。


  • FLEVEL(位于第二个字节的6-7位)
    大致指示压缩级别,范围从0(快速/低)到3(慢速/高)

  • FDICT(位于第二个字节的第5位)
    指示是否使用预设字典。通常为0。(1技术上允许使用,但我不知道有哪些Deflate格式定义了预设字典。)

  • FCHECK(位于第二个字节的0-4位)
    校验和(5位,0..31),其值计算得出整个值除以31没有余数。*


通常情况下,只有CINFOFLEVEL字段可以自由更改,并且FCHECK必须基于最终值进行计算。假设没有预设字典,则不能选择其他字段包含的内容,因此总共有32个可能的头是有效的。它们如下:

      FLEVEL: 0       1       2       3
CINFO:
     0      08 1D   08 5B   08 99   08 D7
     1      18 19   18 57   18 95   18 D3
     2      28 15   28 53   28 91   28 CF
     3      38 11   38 4F   38 8D   38 CB
     4      48 0D   48 4B   48 89   48 C7
     5      58 09   58 47   58 85   58 C3
     6      68 05   68 43   68 81   68 DE
     7      78 01   78 5E   78 9C   78 DA

CINFO 字段很少被压缩软件设置为除 7(表示最大32KB窗口)以外的其他值,因此您可能看到的唯一值是底部行中的四个(以 78 开头)。

* (您可能会想知道在 FCHECK 的值上是否有小幅度的容差 - 如果两者都通过了校验和,它是否可以设置为0或31?实际上,只有在 FDICT = 1 的情况下才会发生这种情况,因此它不出现在上表中。)


2
感谢您提供的详尽信息。这应该是这个问题的被采纳答案。 - Caesar
额外的事实:当FLEVEL为1且CINFO至少为2时,两个字节都是ASCII可打印的,因此(S8OHKXGhCx^都是有效的标头。PNGOUT在压缩图像时使用x^78 5E)。 - mwfearnley

20

以下是Zlib压缩数据格式。

 +---+---+
 |CMF|FLG| (2 bytes - Defines the compression mode - More details below)
 +---+---+
 +---+---+---+---+
 |     DICTID    | (4 bytes. Present only when FLG.FDICT is set.) - Mostly not set
 +---+---+---+---+
 +=====================+
 |...compressed data...| (variable size of data)
 +=====================+
 +---+---+---+---+
 |     ADLER32   |  (4 bytes of checksum)
 +---+---+---+---+

通常情况下,FLG.FDICT(字典标志)未设置。在这种情况下,DICTID不存在。因此,总头部只有2个字节。

没有字典的头部值(CMFFLG)定义如下。

 CMF |  FLG
0x78 | 0x01 - No Compression/low
0x78 | 0x9C - Default Compression
0x78 | 0xDA - Best Compression 

更多内容请参考ZLIB RFC


2
此摘要仅显示了64个可能的zlib头文件中的三个。请参阅mwfearnley的答案。 - Mark Adler

5

这里的所有答案都很可能是正确的,但是 - 如果你想直接操作ZLib压缩流,而它是通过使用gz_open, gzwrite, gzclose函数产生的 - 那么在zlib压缩流之前会有额外的10个字节的头部 - 这些由gz_open函数产生 - 头部看起来像这样:

    fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
         Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);

并且结果如下十六进制转储:1F 8B 08 00 00 00 00 00 00 0B,接着是zlib压缩流。

但是还有8个字节的尾随数据 - 它们是uLong类型 - 对整个文件进行crc校验,uLong类型 - 未压缩的文件大小 - 在流的末尾查找以下字节:

    putLong (s->file, s->crc);
    putLong (s->file, (uLong)(s->in & 0xffffffff));

1
这里有详细的解释:https://tools.ietf.org/html/rfc1952 - Vouze
4
这些是gzip流,不是zlib流。两者不同。 - Mark Adler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接