1. 程式人生 > >gzip,deflate,zlib辨析

gzip,deflate,zlib辨析

(RFC1951):一種壓縮演算法,使用LZ77和哈弗曼進行編碼;
zlib(RFC1950):一種格式,是對進行了簡單的封裝,他也是一個實現庫(delphi中有zlib,zlibex)
gzip(RFC1952):一種格式,也是對進行的封裝。

gzip = gzip頭 + deflate編碼的實際內容 + gzip尾
zlib = zlib頭 + deflate編碼的實際內容 + zlib尾

因最近在做一些關於網頁解碼方面的事情,壓縮都是gzip,deflate.

deflate返回的就是zlib格式。瀏覽器可以解壓,但ie系列要求必需是純正的deflate格式,故解壓時必須手動的新增一個頭和尾,原來採集finance.sina.com.cn上的資料就是deflate格式,今天看了下,改用gzip壓縮了。當時,只在deflate資料前加了兩個位元組:#$78#$9c,就可以用zlib解壓了。

gzip格式和deflate相比,有了一些頭資訊:
GZIP檔案由1到多個“塊”組成,實際上通常只有1塊。每個塊包含頭、資料和尾三部分。塊的概貌如下:

+—+—+—+—+—+—+—+—+—+—+========//========+===========//==========+—+—+—+—+—+—+—+—+
|ID1|ID2| CM|FLG| MTIME |XFL| OS| 額外的頭欄位 | 壓縮的資料 | CRC32 | ISIZE |
+—+—+—+—+—+—+—+—+—+—+========//========+===========//==========+—+—+—+—+—+—+—+—+
1. 頭部分
ID1與ID2:各1位元組。固定值,ID1 = 31 (0×1F),ID2 = 139(0×8B),指示GZIP格式。
CM:1位元組。壓縮方法。目前只有一種:CM = 8,指示DEFLATE方法。
FLG:1位元組。標誌。
bit 0 FTEXT – 指示文字資料
bit 1 FHCRC – 指示存在CRC16頭校驗欄位
bit 2 FEXTRA – 指示存在可選項欄位
bit 3 FNAME – 指示存在原檔名欄位
bit 4 FCOMMENT – 指示存在註釋欄位
bit 5-7 保留

MTIME:4位元組。更改時間。UINX格式。
XFL:1位元組。附加的標誌。當CM = 8時,XFL = 2 – 最大壓縮但最慢的演算法;XFL = 4 – 最快但最小壓縮的演算法
OS:1位元組。作業系統,確切地說應該是檔案系統。有下列定義:
0 – FAT檔案系統 (MS-DOS, OS/2, NT/Win32)
1 – Amiga
2 – VMS/OpenVMS
3 – Unix
4 – VM/CMS
5 – Atari TOS
6 – HPFS檔案系統 (OS/2, NT)
7 – Macintosh
8 – Z-System
9 – CP/M
10 – TOPS-20
11 – NTFS檔案系統 (NT)
12 – QDOS
13 – Acorn RISCOS
255 – 未知

額外的頭欄位:
(若 FLG.FEXTRA = 1)

+—+—+—+—+===============//================+
|SI1|SI2| XLEN | 長度為XLEN位元組的可選項 |
+—+—+—+—+===============//================+
(若 FLG.FNAME = 1)

+=======================//========================+
| 原檔名(以NULL結尾) |
+=======================//========================+
(若 FLG.FCOMMENT = 1)

+=======================//========================+
| 註釋文字(只能使用iso-8859-1字元,以NULL結尾) |
+=======================//========================+
(若 FLG.FHCRC = 1)

+—+—+
| CRC16 |
+—+—+
存在額外的可選項時,SI1與SI2指示可選項ID,XLEN指示可選項位元組數。如 SI1 = 0×41 (‘A’),SI2 = 0×70 (‘P’),表示可選項是Apollo檔案格式的額外資料。

2. 資料部分
DEFLATE資料格式,包含一系列子資料塊。子塊概貌如下:

+……+……+……+=============//============+
|BFINAL| BTYPE | 資料 |
+……+……+……+=============//============+
BFINAL:1位元。0 – 還有後續子塊;1 – 該子塊是最後一塊。
BTYPE:2位元。00 – 不壓縮;01 – 靜態Huffman編碼壓縮;10 – 動態Huffman編碼壓縮;11 – 保留。
各種情形的處理過程,請參考後面列出的RFC文件。

3. 尾部分
CRC32:4位元組。原始(未壓縮)資料的32位校驗和。
ISIZE:4位元組。原始(未壓縮)資料的長度的低32位。
GZIP中位元組排列順序是LSB方式,即Little-Endian,與ZLIB中的相反。

deflate使用inflateInit(),而gzip使用inflateInit2()進行初始化,比 inflateInit()多一個引數: -MAX_WBITS,表示處理raw deflate資料。因為gzip資料中的zlib壓縮資料塊沒有zlib header的兩個位元組。使用inflateInit2時要求zlib庫忽略zlib header。在zlib手冊中要求windowBits為8..15,但是實際上其它範圍的資料有特殊作用,見zlib.h中的註釋,如負數表示raw deflate。
Apache的deflate變種可能也沒有zlib header,需要新增假頭後處理。即MS的錯誤deflate (raw deflate).zlib頭第1位元組一般是0×78, 第2位元組與第一位元組合起來的雙位元組應能被31整除,詳見rfc1950。例如Firefox的zlib假頭為0×7801,python zlib.compress()結果頭部為0×789c。

注:以上文字屬於多段摘抄,非原創。收錄於此,感謝原作者們。