解析 zlib header

Parsing zlib header

我花了几天时间阅读 zlib(以及 gzip 和 deflate)RFC,我可以说它们有点垃圾。缺少很多细节,所以我打开这个问题。

我正在尝试解析 zlib 数据,我需要了解有关 header 的一些详细信息。

首先,RFC说会有2个字节,CMFFLG

CMF 分为 2 个 4 位部分。第一个是 CM 第二个是 CINFO.

CM 的可能值是多少? RFC 说 8 表示 deflate 并且 15 是保留的,但是其余可能的值呢?

CINFO 另一方面,如果我正确理解 RFC(如果我错了,请纠正我),应该始终为 8。

跳过 FLG 和可能的 FDICT,我们进入 Compressed data 部分。 RFC 的这一部分说:

For compression method 8, the compressed data is stored in the
deflate compressed data format as described in the document
"DEFLATE Compressed Data Format Specification" by L. Peter
Deutsch. (See reference [3] in Chapter 3, below)

这是什么意思?我应该假设 CM 永远是 8 吗?如果 yes,那么为什么整个 CM 存在?

最后,我有点困惑。我始终相信 zlib 可以包装 deflate 和 gzip,但是阅读此 RFC 我看不到 gzip 压缩数据适合放在这里的什么地方。我对此有什么遗漏吗?

What are the possible values of CM? RFC says that 8 means deflate and that 15 is reserved, but what about the rest of the possible values?

...

Should I assume that CM will always be 8? If yes, then why does the entire CM thing exists?

CM 供将来使用并允许其他 (non-standard) 压缩方法:

此版本的 zlib 规范中未指定其他压缩数据格式。 (RFC 1950, "ZLIB Compressed Data Format Specification version 3.3")

你不应该假设它总是 8。相反,你应该检查它,如果它不是 8,抛出一个“不支持”的错误。


CINFO on the other side, should be always 8, if I understand the RFC correctly (please correct me if I'm wrong).

不是,CINFO的意义取决于CM。如果 CM 是 8(唯一有意义的标准化值),则:

CINFO 是 LZ77 window 大小的以 2 为底的对数减去八(CINFO=7 表示 32K window 大小)。此版本规范中不允许 CINFO 大于 7 的值。 (RFC 1950, "ZLIB Compressed Data Format Specification version 3.3")

所以实际上 CINFO 不能 是 8.


Skipping FLG and the possible FDICT, we get to the Compressed data section. This part of the RFC says:

For compression method 8, the compressed data is stored in the
deflate compressed data format as described in the document
"DEFLATE Compressed Data Format Specification" by L. Peter
Deutsch. (See reference [3] in Chapter 3, below)

What does this mean?

这意味着 DEFLATE 编码的详细信息未在此标准中指定,但在别处描述,在 ftp://ftp.uu.net/pub/archiving/zip/zlib/

如果您愿意,DEFLATE 有自己的 RFC,即 RFC 1951, "DEFLATE Compressed Data Format Specification version 1.3"


Last, I'm a bit confused. I always believe zlib can wrap both deflate and gzip, but reading this RFC I can't see where a gzip compressed data fits in here. Is there anything that I'm missing about this?

不,zlib 不能打包 gzip。 gzip 和 zlib 是压缩数据的不同包装器(zip 格式、PNG 格式、PDF 格式等)

Gzip 使用 DEFLATE:

该格式目前使用 DEFLATE 压缩方法,但可以轻松扩展为使用其他压缩方法。 (RFC 1952, "GZIP file format specification version 4.3")

CM = 8表示“deflate”压缩方式,window大小可达32K。这是gzip和PNG(RFC 1950, "ZLIB Compressed Data Format Specification version 3.3")

使用的方法

如果您发现 RFC 不清楚或难以理解,请考虑查看 zlib 实现的源代码。虽然有些实现可能是 non-standard,但查看源代码可能会帮助您解决一些疑惑。

以下是 zlib from zlib.net 源代码的摘录,可以回答您的一个问题:

#define Z_DEFLATED   8
/* ... */
if (BITS(4) != Z_DEFLATED) { 
    strm->msg = (char *)"unknown compression method";
    state->mode = BAD;
    break;
}