gzcompress如何工作?

时间:2010-07-08 09:28:20

标签: php compression gz

我想知道为什么在使用gzcompress()之后我需要切掉最后4个字符。

这是我的代码:

header("Content-Encoding: gzip");
echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
$index = $smarty->fetch("design/templates/main.htm") ."\n<!-- Compressed by gzip -->";
$this->content_size = strlen($index);
$this->content_crc = crc32($index);
$index = gzcompress($index, 9);
$index = substr($index, 0, strlen($index) - 4); // Why cut off ??
echo $index;
echo pack('V', $this->content_crc) . pack('V', $this->content_size);

当我不剪切最后4个字符时,源代码结束如下:

[...]
<!-- Compressed by gzip -->N

当我将它们剪掉时,它会显示:

[...]
<!-- Compressed by gzip -->

我只能在Chromes Code检查器中看到额外的N(不是在Firefox中,而是在IEs源中)。但是在代码的末尾会有四个附加字符。

任何人都可以解释一下,为什么我需要切断4个字符?

2 个答案:

答案 0 :(得分:7)

gzcompress实现了ZLIB compressed data format的<{3}}:

     0   1
   +---+---+
   |CMF|FLG|   (more-->)
   +---+---+

(if FLG.FDICT set)

     0   1   2   3
   +---+---+---+---+
   |     DICTID    |   (more-->)
   +---+---+---+---+

   +=====================+---+---+---+---+
   |...compressed data...|    ADLER32    |
   +=====================+---+---+---+---+

在这里您可以看到最后四个字节是following structure

与此相反,Adler-32 checksum是所谓成员的列表,具有以下结构:

   +---+---+---+---+---+---+---+---+---+---+
   |ID1|ID2|CM |FLG|     MTIME     |XFL|OS | (more-->)
   +---+---+---+---+---+---+---+---+---+---+

(if FLG.FEXTRA set)

   +---+---+=================================+
   | XLEN  |...XLEN bytes of "extra field"...| (more-->)
   +---+---+=================================+

(if FLG.FNAME set)

   +=========================================+
   |...original file name, zero-terminated...| (more-->)
   +=========================================+

(if FLG.FCOMMENT set)

   +===================================+
   |...file comment, zero-terminated...| (more-->)
   +===================================+

(if FLG.FHCRC set)

   +---+---+
   | CRC16 |
   +---+---+

   +=======================+
   |...compressed blocks...| (more-->)
   +=======================+

     0   1   2   3   4   5   6   7
   +---+---+---+---+---+---+---+---+
   |     CRC32     |     ISIZE     |
   +---+---+---+---+---+---+---+---+

如您所见,GZIP使用GZIP file format进行完整性检查。

所以要分析你的代码:

  • echo "\x1f\x8b\x08\x00\x00\x00\x00\x00"; - 输出以下标题字段:
    • 0x1f 0x8b - ID1和ID2,用于标识数据格式的标识符(这些是固定值)
    • 0x08 - CM,使用的压缩方法; 8表示使用CRC-32 checksum
    • 0x00 - FLG,flags
    • 0x00000000 - MTIME,修改时间
    • 字段XFL(额外标志)和OS(操作系统)由DEFLATE数据压缩格式设置
  • echo $index; - 根据DEFLATE数据压缩格式输出压缩数据
  • echo pack('V', $this->content_crc) . pack('V', $this->content_size); - 以二进制形式输出CRC-32校验和和未压缩输入数据的大小

答案 1 :(得分:2)

gzcompress产生这里描述的输出RFC1950,你正在切断的最后4个字节是adler32校验和。这是“deflate”编码,所以你应该设置“Content-Encoding:deflate”而不是操纵任何东西。

如果您想使用gzip,请使用gzencode(),它使用gzip format