GZIP壓縮原理分析(04)——第三章 gzip文件格式詳解(三02) gzip文件頭

文件頭由固定長度的部分和擴展部分組成,擴展部分不一定存在,尤其是網絡傳輸使用的HTTP壓縮,如果使用了gzip格式,那麼對應的壓縮報文一般都不帶擴展部分。gzip文件格式通過將頭部中定長部分的某些比特位置位來標識頭部是否帶有擴展部分,我們一一來看。

 

以下各字段的中文含義,我在網上搜了好久也沒找到理想的,這裏我將RFC1952中的英文釋義粗略的翻譯一下,不足之處歡迎吐槽。

 

1、 文件以10字節的定長部分開始

+------+------+------+-------+---+---+---+---+------+-----+

ID1   |  ID2  |   CM  |   FLG   |       MTIME       |  XFL  |  OS  |

+------+------+------+-------+---+---+---+---+------+-----+

上面兩個“+”之間的內容代表一個字節,所以上面除了MTIME使用四個字節之外,其他只佔用一個字節。

 

ID1ID2IDentification:這兩個字節用於標識gzip文件,其中,ID1 = 31(0x1f,\037),ID2 = 139(0x8b,\213),如果判斷某文件以這兩個字節開頭,那麼可以初步認爲這是gzip文件,但具體是不是,必須該文件格式完全符合gzip文件格式才行;

CM(CompressionMethod):該字段用於標識當前gzip壓縮文件內部的壓縮結果所使用的壓縮方法,取值範圍[0,8](提示,這是一個閉區間),其中,[0,7]保留,目前只用8,即gzip使用deflate壓縮方法;

FLG(FLaGs):標記位,該標記位中的每一比特分別代表後面對應擴展位是否存在,各比特位含義如下, 

   Bit 0        FTEXT

   Bit 1        FHCRC

   Bit 2        FEXTRA

   Bit 3        FNAME

   Bit 4        FCOMMENT

   Bit 5~7   預留,必須全0

Bit 0     FTEXT,如果置位,則表明文件(應該是指被壓縮文件)是ASCII文本文件。這一位是否置位是可選的,壓縮工具通過檢查少量輸入數據中是否含有非ASCII字符來將其置位。一旦懷疑有非ASCII字符,就不置位,表示這是二進制文件。那些對ASCII文本文件和二進制文件使用不同文件格式的系統,解壓縮工具會通過這一位是否置位來決定合適的文件格式。我們故意不讓壓縮所使用的算法來設置這一位,因爲壓縮工具本身可以選擇是否將其置位,而且解壓縮工具通常也可以選擇忽略這一位並將數據轉換的問題拋給其他程序。

Bit 1     FHCRC,如果置位,表示會對gzip文件頭部進行CRC16校驗,校驗結果會放在實際的壓縮數據之前,緊挨着實際的壓縮數據。CRC16由CRC32的兩個低有效字節組成,CRC32用於計算整個gzip頭的校驗和,但計算時不包括CRC16所佔的這兩個字節。這一位一般不會被置上。(注意:這裏說的這個CRC32與我們後面要說的位於gzip文件尾的那個CRC32不是同一個CRC32!!!但都是用32位循環冗餘校驗碼算法計算得到的,只是作用對象不同。這裏的CRC32作用對象是gzip頭,完成計算後只取兩個低有效字節,構成CRC16;而我們後面要說的位於gzip文件尾的CRC32的作用對象是全部的原始待壓縮數據,這兩個概念一定要理清)。

Bit 2     FEXTRA,如果置位,表示帶着擴展gzip頭部部分。擴展部分後續介紹。

Bit 3     FNAME,如果置位,表示攜帶被壓縮文件的文件名(沒被壓縮),該文件名會以’\0’結束(就是個字符串)。該文件名必須由ISO 8859-1 (LATIN-1) 中的字符組成;在那些使用EBCDIC或其他字符集組成名稱的系統中,文件名稱必須被轉換爲ISO LATIN-1 字符集才能讓gzip文件攜帶。這個文件名是被壓縮文件的原始文件名,不攜帶任何的路徑信息,只是個文件名而已。如果被壓縮文件在一個對名稱字母大小寫不敏感的文件系統上,則文件名稱必須全部小寫。如果被壓縮數據不是來自一個有文件名稱的文件,則不攜帶文件名稱(比如使用gzip壓縮HTTP應答報文);例如,被壓縮數據來自Unix系統的標準輸入,則gzip文件不攜帶文件名。

Bit 4     FCOMMENT,如果置位,表示攜帶以‘\0’結尾的文件說明(這個文件說明也是個字符串)。這個說明只是給人們去使用的,類似HTTP應答報文頭部中的狀態碼原因短語。這個文件說明也必須使用ISO 8859-1 (LATIN-1)中的字符。換行時應該用一個十進制換行符。

MTIMEModificationTIME:該字段給出了那個被壓縮的原始文件最近被修改的時間。該時間使用Unix格式,即,自1970年1月1日0時起到現在的秒數。注意,對於MS-DOS或其他使用本地時間而不是使用通用時間的系統,這種方式可能會引起問題。如果不是壓縮一個文件,那麼該字段就是壓縮工作開始的那個時間。如果該字段爲0,則表示沒有可用的時間戳(這種情況在使用gzip的HTTP壓縮報文中很常見)。

XFLeXtraFLags:這個字段是專門給gzip文件中使用的壓縮方法用的,由於當前gzip只使用一種壓縮方法,或壓縮算法,即deflate,所以針對deflate,該字段有如下含義,

XFL= 2 – 壓縮率最大但是壓縮速度最慢(的那個壓縮級別);

XFL= 4 – 最快的壓縮(級別);

(注:deflate 是分0~9種壓縮級別的,後續分析壓縮源碼的章節會專門分析壓縮級別)

OSOperatingSystem:這個字段表示幹壓縮這件事兒的那個文件系統。這個字段對於確定文本文件的行結束標誌是非常有用的。這個字段的當前值分別代表如下系統,

0- FAT filesystem (MS-DOS, OS/2, NT/Win32)

1- Amiga

2- VMS (or OpenVMS)

3- Unix

4- VM/CMS

5- Atari TOS

6- HPFS filesystem (OS/2, NT)

7- Macintosh

8- Z-System

9- CP/M

10- TOPS-20

11- NTFS filesystem (NT)

12- QDOS

13- Acorn RISCOS

255– unknown

 

2、 頭部擴展字段

上面10個字節是無論如何都會存在的,而這裏所描述的擴展字段,就是根據上面那10個字節來決定是否存在的。共分爲四個部分,

按照順序依次是:FEXTRA+FNAME+FCOMMENT+FHCRC

不一定都會存在,但是隻要存在,不論存在幾個,一定要按照順序來,例如,FHCRC 和FNAME都存在,那麼FNAME 一定要在FHCRC前面!!!下面我們逐個分析。

FEXTRA

+-----+-----+===============================================+

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

+-----+-----+===============================================+

XLEN用兩個字節記錄,表示extra field部分的大小。而extra field部分又細分爲如下結構,

                   +--------+--------+--------+--------+========================+

                    |    SI1    |     SI2    |          LEN           |…………... LEN bytes ofsubfield data ...|

                   +--------+--------+--------+--------+========================+

(我將這個部分翻譯爲次級域)SI1和SI2爲這個次級域提供一個ID,這個ID通常由兩個便於記憶的ASCII字母表示(這句話不知道是不是應該這麼翻譯)。Jean-Loup Gailly[email protected](gzip源碼作者)維護了一張次級域表,你可以將自己的次級域ID發送給他。SI2 = 0 的次級域ID目前保留,未來再用。現在的次級域ID是這樣定義的,

       SI1       |        SI2       |        Data

 ----------      ----------     -------------

  0x41('A')      0x70 ('P')       Apollo file typeinformation(這個真不知道這麼翻譯)

LEN給出了次級域數據部分的長度,但是不包括SI1、SI2和LEN這四個字節。

FNAME

+=========================================+

|...originalfile name, zero-terminated...| (more-->)

+=========================================+

以‘\0’結束,就是個字符串

FCOMMENT

+===================================+

|...filecomment, zero-terminated...| (more-->)

+===================================+

以‘\0’結束,就是個字符串

FHCRC

+-------+-------+

|       CRC16        |

+-------+-------+

這個後面就是實際的壓縮數據了,也就是蝦的身子部分。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章