1.字符集與編碼
字符集:表示多個字符的集合,如符號,序號、數字,其它等等。
字符編碼:把字符編碼為指定集合中的某一對象,變成一種特定的字節或字節序列,在計算機中便于存儲,傳輸。
通常字符集都采用對應的編碼方式,如ASCII、IOS-8859-1、GB2312、GBK,即表示了字符集又表示了對應的字符編碼,但是Unicode例外,它采用的現代模型。

2.字符集編碼的發展
字符集編碼的發展,從單字節,發展到雙字節,最終到多字節。
(1)單字節
ASCII,用 7 位二進制表示(00000000-01111111 即 0x00-0x7F)。EASCII(Extended ASCII),256 個字符,用 8 位二進制表示(00000000-11111111 即 0x00-0xFF)。
(2)雙字節
當計算機傳到了亞洲,256 個碼位就不夠用了。于是乎繼續擴大二維表,單字節改雙字節,16 位二進制數,65536 個碼位。在不同國家和地區又出現了很多編碼,大陸的 GB2312、港臺的 BIG5、日本的 Shift JIS 等等。
雙字節編碼是可以變長,主要是為了兼容ASCII碼和節省存儲容量,但是可能會損失一部分碼位。
UNICODE 字符集國際標準字符集,它將世界各種語言的每個字符定義一個唯一的編碼,以滿足跨語言、跨平臺的文本信息轉換。有多個編碼方式,分別是 UTF-8,UTF-16,UTF-32 編碼。
(3)多字節
UTF表示Unicode Transformation Format的縮寫,是一種Unicode轉換格式,后面的數字表示至少用多少個比特位來存儲字符。
UTF-8表示一種變長編碼方案,使用1-6個字節來存儲;
UTF-16使用2個或4個字節來存儲,長度固定又可變。
UTF-32表示一種固定長度編碼方案,使用4個字節來存儲。
Utf8前綴編碼格式如下:

當Unicode 編號范圍在 0~FFFF 之間的字符,UTF-16 使用兩個字節存儲,并且直接存儲 Unicode 編號,不用進行編碼轉換,這跟 UTF-32 非常類似。當Unicode 編號范圍在 10000~10FFFF 之間的字符,UTF-16 使用四個字節存儲。實際就把較高的一些比特位用D800~DBFF 之間的雙字節存儲,較低的比特位用DC00~DFFF之間的雙字節存儲。

UTF-32 是固定長度的編碼,始終占用 4 個字節,足以容納所有的 Unicode 字符,所以直接存儲 Unicode 編號即可,不需要任何編碼轉換。浪費了空間,提高了效率。
UTF大小端問題
BOM實際就是使用大端(BE)還是小端(LE)問題。
UTF-16BE,大端:就是把高位字節放在低地址表示。
UTF-16LE,小端:就是把低字節放在低地址表示。
UTF在文件的存儲。UTF格式在文件中總有固定文件頭。UTF-8缺省不帶BOM。
當打開一個文件時,怎么識別使用的是UTF-8還是UTF-16.在文件的開頭就是標志。
EF BB BF 表示 UTF-8
FE FF 表示 UTF-16BE
FF FE 表示 UTF-16LE
00 00 FE FF 表示 UTF32-BE
FF FE 00 00 表示 UTF32-LE
注意:只有UTF-8兼容ASCII,UTF-32和UTF-16都不兼容ASCII,因為這連個沒有單字節編碼。
iconv
iconv命令用來轉換文件的編碼,如將UTF8編碼轉換成GB18030的編碼,linux下的iconv開發庫包括iconv_open,iconv_close,iconv等C函數,實現快速轉換。
格式:
iconv -f encoding [-t encoding] [inputfile] ....
選項:
-f encoding :字符從encoding編碼開始轉換
-t encoding :字符轉換到encoding編碼
-l:已知的編碼字符集合
-o file :指定輸出文件
-c :忽略輸出的非法字符
-s :禁止警告信息,但不是錯誤信息
--verbose :顯示進度信息
查看支持的格式: iconv -l
UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, UTF-32LE, UTF8, UTF16, UTF16BE, UTF16LE, UTF32, UTF32BE, UTF32LE GB2312 ,GBK ISO-8859-1。
轉換各種格式:

字符集轉換編程:
#include <iconv.h>
函數:iconv_t iconv_open (const char* tocode, const char* fromcode);
范例:iconv_t cd = iconv_open(“UTF−8”, “UTF−16”);
函數:int iconv_close (iconv_t cd);
范例:iconv_close(cd);
函數:size_t iconv (iconv_t cd, const char* * inbuf, size_t * inbytesleft, char* * outbuf,
size_t * outbytesleft);
返回值:返回-1 則說明出現異常,錯誤碼
E2BIG:outbuf 沒有足夠的空間
EILSEQ:遇到無效的多字節序列
EINVAL:遇到不完整的多字節序列
字符集在線工具集合
GBK 內碼查詢:
http://www.mytju.com/classcode/tools/encode_gb2312.a
完整的 Unicode 字符集:
https://unicode-table.com/c
Unicode 和 UTF 編碼轉換:
https://www.qqxiuzi.cn/bianma/Unicode-UTF.p
漢字字符集編碼查詢:
https://www.qqxiuzi.cn/bianma/zifuji.p
3.壓縮原理
壓縮原理就是找到重復出現的字符串,然后用更短的符號代替,從而達到縮短字符串的目的。本質上,所謂就是找出文件內容的概率分布,將出現概率高的部分代替為更短的形式。內容越重復的文件,可以壓縮的越小。如,"ABABABABABABAB"可以壓縮成"7AB"。反之內容毫無重復,就很難壓縮,極端情況就是,均勻分布的隨機字符串,往往一個字符都無法壓縮,如任意排列的10個阿拉伯數組(123456789),就無法壓縮,再如π,也很難。
香農極限
∑ log2(1/pn) / n = log2(1/p1)/n + log2(1/p2)/n + ... + log2(1/pn)/n;
(1)如果兩個文件都包含了1024個符號,在ASCII 碼情況下,長度是相等,A文件(只包含abc)的內容50%是 a,30%b,20%是 c,則平均每個符號要占用1.49個二進制位。
0.5*log2(1/0.5) + 0.3*log2(1/0.3) + 0.2*log2(1/0.2) = 1.49
(2)假如B文件的每個字節出現的概率是0-255,均勻分布的出現概率是1/256,則 pn = 1/256,計算出極限為 8。
Log21/(1/256) = Log2256 = 8
4.Deflate 壓縮算法
deflate是一種壓縮數據流的算法,任何需要流式壓縮的地方都可以,deflate是zip壓縮文件的默認算法,除了zip文件,還有7z,xz等其他壓縮文件,也是用。
deflate 算法下的壓縮器有三種壓縮模型:
(1)不壓縮數據,對于已經壓縮的數據,不再壓縮,這樣的數據會稍微增加,但會小于其它應用的一種壓縮算法。
(2)先用L7zz,再用huffman 編碼。壓縮的樹是Deflate規范定義,所以不需要額外的空間來存儲這個樹。
(3)先用LZ77,然后再用huffman 編碼。壓縮樹由壓縮器生成,并與數據一起存儲。
如果數據被分割成不同塊,必須使用單一的壓縮模式,如果要在這三種壓縮模式中相互切換,必須先結束當前塊,重新開始一個新的塊。
5.LZ77 算法原理
采用字典的方式進行壓縮,是一個簡單高效的數據壓縮算法。把數據中的一些可以組織成短語的字符加入字典,然后再有相同字符出現采用畢節來代替字典中的短語,如此通過標記代替多數重復出現的方式以進行壓縮。需先了解 3 個關鍵詞:短語字典,滑動窗口和向前緩沖區。
(1)前向緩沖區
每次讀取數據的時候,先把一部分數據預載入前向緩沖區。為移入滑動窗口做準備
(2)一旦數據通過緩沖區,那么它將移動到滑動窗口中,并變成字典的一部分?;瑒哟翱谛枰A設一個定值。
(3) 比如字符(A,B,D) ,可以組合的短語為{(A),(A,B),(A,B,D),(B),(B,D),(D)},如果這些字符在滑動窗口里面,可以標記為當前的短語字典,滑動窗口不斷向前滑動,短語字典也不斷變化。
注意:先通過前向緩沖區預讀數據,然后再向滑動窗口移入(滑動窗口有一定長度),在這個過程中,不斷尋找與字典中短語匹配的最長短語,最終通過標記符標記,以ABD為例子。這里滑動窗口 和前向緩沖區可以匹配的最長短語是(A,B),然后向前移動的時候再次遇到(A,B)的時候采用標記符代替。

當壓縮數據的時候,前向緩沖區與移動窗口之間在做短語匹配的是后會存在 2 種情況:
(1)找不到匹配時:將未匹配的符號編碼成符號標記(多數都是字符本身)
(2)找到匹配時:將其最長的匹配編碼成短語標記。
短語標記包含三部分信息:
(1)滑動窗口中的偏移量(從匹配開始的地方計算);
(2)匹配中的符號個數;
(3)匹配結束后的前向緩沖區中的第一個符號。
一旦把 n 個符號編碼并生成相應的標記,就將這 n 個符號從滑動窗口的一端移出,并用前向緩沖區中同樣數量的符號來代替它們,如此,滑動窗口中始終有最新的短語。
(1)開始

(2) 滑動窗口中沒有數據,所以沒有匹配到短語,將字符 A 標記為 A

(3)滑動窗口中有 A,沒有從緩沖區中字符(BABC)中匹配到短語,依然把 B 標記為
B

(4)緩沖區字符(ABCB)在滑動窗口的位移 6 位置找到 AB,成功匹配到短語 AB,將AB 編碼為(6,2,C),之所以是 6,是因為窗口的 A 在滑動窗口的索引[6]位置。

(5)緩沖區字符(BABA)在滑動窗口位移 4 的位置匹配到短語 BAB,將 BAB 編碼為
(4,3,A)。

(6) 緩沖區字符(BCAD)在滑動窗口位移 2 的位置匹配到短語 BC,將 BC 編碼為
(2,2,A)

(7) 緩沖區字符 D,在滑動窗口中沒有找到匹配短語,標記為 D

(8)緩沖區中沒有數據進入了,結束

6.LZ77解壓
解壓就是壓縮的逆向過程,當解碼字符標記:將標記編碼成字符拷貝到滑動窗口中,解碼短語標記:在滑動窗口中查找相應變量,同時找到指定長短的短語進行替換。
(1)開始

(2)符號標記 A 解碼

(3)符號標記 B 解碼

(4)短語標記(6,2,C)解碼。根據 3 中的索引[6]開始,得到 AB,就是重復 AB 再加入上 C,就成了 ABABC,并且滑動窗口滑到最右邊的位置。

(5)短語標記(4,3,A)解碼
根據4中的進行標記。

(6)短語標記(2,2,A)解碼
根據5中進行標記。

(7) 符號標記 D 解碼

LZ77 壓縮算法優點:
壓縮比相當高。也和你選擇滑動窗口大小,以及前向緩沖區大小,以及數據熵有關系。
解壓很快,每個標記都明確告知在哪個位置可以讀取。
缺點:
壓縮過程是比較耗時的,因為要花費很多時間尋找滑動窗口中的短語匹配。
6.Huffman 算法原理
哈夫曼設計了一個貪心算法來構造最優前綴碼,被稱為哈夫曼編碼(Huffman code),其正確性證明依賴于貪心選擇性質和最優子結構。哈夫曼編碼可以很有效的壓縮數據,具體壓縮率依賴于數據本身的特性。
先介紹幾個概念:碼字、碼字長度、定長編碼與變長編碼。
碼字:每個字符可以用一個唯一的二進制串表示,這個二進制串稱為這個字符的碼字。
碼字長度:這個二進制串的長度稱為碼字長度。碼字長度不變就是固定編碼,否則就是變長編碼。變長編碼可以達到比定長編碼好得多的壓縮率。其核心思想就是賦予高頻字符(出現頻率高的字符)短(碼字長度較短)碼字,賦予低頻字符長碼字。
如果一個文檔中,每個字符出現的頻率基本一樣,那變長編碼的優勢在壓縮方面的優勢就不存在了。
哈弗曼會自底向上構造出一棵對應最優編碼的二叉樹,下面舉例來說明。某個文件中有如下字符及其概率。
字符 a b c d e f
概率 45 13 12 16 9 5
構造過程如下圖所示:
每個字符都已
經按照出現頻率大小排好順序,在后續的步驟中,每次都將頻率最低的兩棵樹合并,然后用合并后的結果再次排序。注意,排序不是目的,目的是找到這時出現頻率最低的兩項,以便下次合并,gzip 源碼中并沒有專門去“排序”,而是使用專門的數據結構把頻率最低的兩項找到即可。
在葉子節點用矩形表示,每個葉子節點包含一個字符及其頻率。中間節點用圓圈表示,包含其孩子節點的頻率之和。中間節點指向左孩子的邊標記為 0,指向右孩子的邊標記為 1。第6步驟的每個字符的編碼都是前綴碼。
(1) 按照頻率大小先排序

(2)把f和e拿出來組成一個子樹,并相加,再把子樹相加的結果,再次進行排序

(3)在重復前面的排序和最小的兩個概率相加操作

(4)依次重復之前的操作

(5)依次重復之前的操作

(6)依次重復之前的操作

代碼思想:
利用庫中的優先級隊列實現哈夫曼樹,最后基于哈夫曼樹最終實現文件壓縮。
(1)統計文件中字符出現的次數,利用優先級隊列構建 Haffman 樹,生成 Huffman 編碼。構造過程中可以使用priority_queue 輔助,每次 pq.top()都可以取出權值(頻數)最小的節點。每取出兩個最小權值的節點,就 new 出一個新的節點,左右孩子分別指向它們。然后把這個新節點 push 進優先隊列。
(2)壓縮,實際就是存入壓縮編碼。利用 Haffman 編碼對文件進行壓縮,即在壓縮文件中按順序存入每個字符的 Haffman 編碼。

(3)將文件中出現的字符以及它們出現的次數寫入配置文件中,以便后續壓縮使用。
(4)解壓縮:利用配置文件重構 Haffman 樹,對文件進行減壓縮
后面的文章會來詳細分析代碼:
7.deflate 采用的改進版 LZ77 算法
三個字節以上的重復串才進行編碼,否則不進行編碼:
為什么最小匹配3個字節?
gzip 中,<匹配長度,到匹配串開頭的距離>對中,"匹配長度"的范圍為 3-258,也就是 256 種可能值,需要 8bit來保存。"到匹配串開頭的距離"的范圍為 0-32K,需要 15bit 來保存。所以一個<匹配長度,到匹配串開頭的距離>對需要 23 位,差一位 3 個字節。如果匹配串小于 3 個字節的話,使用<匹配長度,到匹配串開頭的距離>對進行替換,不但沒有壓縮,反而還會增大。所以保存<匹配長度,到匹配串開頭的距離>對所需要的位數,決定了最小匹配長度至少要為 3 個字節。
deflate 無損壓縮解壓算法
先 LZ77 壓縮,再用huaffman編碼。
deflate 中的 huffman 編碼:
對 LZ77 得到的壓縮后結果,需要統計字符生成編碼表 huffmantree(指示每個編碼代表什么字符),根據碼表對內容進行編碼,具體的壓縮大小在于精細分配結構體的位域來實現 Huffman 編碼的壓縮效果的。編碼表huffmantree和編碼后的data都一起放置在文件中。
deflate 中的解壓:
讀取二進制文件,構建huffmantree 表,讀取數據根據huffmantree 生成字符。LZ77 解碼需要對窗口生成哈希表(數組+鏈表),對解壓的數據,進行搜索匹配拷貝替換為相應的串即可。
8.gzip 格式分析
GZIP 本身只是一種文件格式,其內部通常采用 DEFLATE 數據格式,而 DEFLATE 采用 LZ77 壓縮算法來壓縮數據。GZIP 文件由 1 到多個“塊”組成,實際上通常只有 1 塊。每個塊包含頭、數據和尾三部分。塊的概貌如下:
gzip = gzip 頭 + deflate 編碼的實際內容 + gzip 尾
zlib = zlib 頭 + deflate 編碼的實際內容 + zlib 尾

(1)頭部分
ID1 與 ID2:各 1 字節。固定值,ID1 = 31 (0x1F),ID2 = 139(0x8B),指示 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 字節。更改時間。
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)
(2)數據部分
DEFLATE 數據格式,包含了一系列子數據塊。結構如下:

BFINAL:1 比特。0 - 還有后續子塊;1 - 該子塊是最后一塊。BTYPE:2 比特。00 -- 不壓縮,01--靜態Huffman編碼壓縮。10--動態Huffman 編碼壓縮。11--保留。
(3)尾部分
CRC32:4 字節。原始數據的32位校驗和。ISIZE:4 字節。原始數據長度的低32位。
GZIP 中字節排列順序是 LSB 方式,即 Little-Endian,與 ZLIB 中的相反。
9.zlib 庫 API 分析
(1)下載源碼包
下載 http://www.zlib.net/,選擇 zlib-1.2.11.tar.gz
(2)下載
wget http://www.zlib.net/zlib-1.2.11.tar.gz
(3)解壓
tar -zxvf zlib-1.2.11.tar.gz
(3)進入目錄
cd zlib-1.2.11
(4)配置
./configure
(5)編譯
make
(6)檢查,要全部為 yes
make check
(4)安裝
sudo make install
基礎數據結構:



壓縮函數:
deflateInit :參數比較少,里面實際就是調用deflateInit2
deflateInit2:
deflate : 壓縮函數。
deflateEnd :壓縮完成后,釋放空間,注意,僅僅釋放deflateInit 中申請的空間,自己申請的空間還是要自己釋放。
compress :全部附加選項默認壓縮,內部調用 compress2。
compress2 : 帶 level 的壓縮方式。
deflateInit2 : 初始化函數

功能:壓縮初始化內部流狀態,zalloc,zfree和opaque字段必須在調用之前初始化,若zalloc 和 zfree 被初始化為 Z_NULL,deflateInit會更新它們而使用默認的分配函數。
壓縮級別為Z_DEFAULT_COMPRESSION,使用0到9之間的數,1表示最快速度的壓縮,9表示最優壓縮,0表示不做任何壓縮,Z_DEFAULT_COMPRESSION是速度和最優壓縮的折衷。
level: 壓縮的等級,目前有四個值
#define Z_NO_COMPRESSION 0 //不壓縮
#define Z_BEST_SPEED 1 //速度優先,可以理解為最低限度的壓縮.
#define Z_BEST_COMPRESSION 9 //壓縮優先,但是速度會有些慢
#define Z_DEFAULT_COMPRESSION (-1) //默認選項,compress 里面用的就是這個選
項
返回值:
成功返回Z_OK,沒有足夠的內存則返回 Z_MEM_ERROR,若壓縮級別無效,返回Z_STREAM_ERROR,版本不兼容則返回 Z_VERSION_ERROR。如果沒有錯誤信息則 msg 被設置為 0。
z_stream:這個是壓縮上下文。
strm.zalloc = NULL;
strm.zfree = NULL;
strm.opaque = NULL;
strm.next_in = 你的待壓縮數據
strm.next_out = 壓縮以后數據存儲的 buffer
strm.avail_in = 待壓縮數據的長度
strm.avail_out = 壓縮數據存儲 buffer 的長度.
method: 值只有一個,當前唯一的 defalte 壓縮方法,用于以后擴展
#define Z_DEFLATED 8
/* The deflate compression method (the only one supported in this version)
*/
windowBits: 窗口比特數
-(15 ~ 8) : 純 deflate 壓縮
+(15 ~ 8) : 帶 zlib 頭和尾
> 16 : 帶 gzip 頭和尾
memLevel: 目前只有一個選項,MAX_MEM_LEVEL,無非是運行過程中對內存使用的限制.
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
strategy :用于調整壓縮算法,直接給默認就行 Z_DEFAULT_STRATEGY
#define Z_FILTERED 1 //用于由 filter(或者稱為 predictor)生成的數據
#define Z_HUFFMAN_ONLY 2 //用于強制哈夫曼編碼(不做字符匹配)
#define Z_RLE 3 //限制匹配長度為 1
#define Z_FIXED 4 //阻止使用動態哈夫曼編碼,從而允許獲得更簡單的解碼
#define Z_DEFAULT_STRATEGY 0 //用于普通數據
Z_FILTERED,用于由 filter(或者稱為 predictor)生成的數據.過濾的數據包含很多小的隨機數據。這種情況下,壓縮算法能夠獲得更好的壓縮效果。該選項可以強制更多的哈夫 曼 編 碼 和 更 少 的 字 符 匹 配 。 有 時 候 可 以 作 為 Z_DEFAULT_STRATEGY 和
Z_HUFFMAN_ONLY 的折衷。
Z_FIXED,阻止使用動態哈夫曼編碼,從而允許獲得更簡單的解碼。
strategy 參數只影響壓縮比,而不會影響到壓縮輸出的正確性,因此沒有正確的設置也不要緊
deflate函數盡可能壓縮數據,當輸入緩存為空或輸出緩沖滿了就會停止,帶來輸出延遲,除非強行刷新緩沖區。

deflate 會執行下面的一個或者兩個動作都執行,avail_in或avail_out 被設置,使用提供更多輸入數據和消耗更多輸出數據的方式,
(1)從 next_in 開始壓縮輸入數據,進而更新next_in 和 avail_in。如果不是所有輸入數據可以被處理(緩沖沒有足夠的空間),next_in和avail_in會更新,當再次調用deflate()函數時輸入數據會從這一點開始被處理。從而更新avail_in 或 avail_out;avail_out 在函數調用之前千萬不能為 0。應用程序可以隨時消耗被壓縮的輸出數據。如輸出緩存滿或每次調用deflate()之后,若deflate返回Z_OK并avail_out 為 0 時,deflate()必須再次被調用(說明輸出緩存區還有數據應該被讀取)
(2)next_out 開始提供更多輸出數據從而更新 next_out 和 avail_out,如果 flush參數不是為 0 的化這個動作是強制性的,經常性的強制刷新緩存會降低壓縮比率,只有必要的時候去設置這個參數。
Int flush 的參數:
Z_NO_FLUSH:允許壓縮算法累計產生多少數據再輸出,以達到壓縮率最高。
Z_SYNC_FLUSH:將所有等待輸出的數據刷新到輸出緩沖區,以字節為邊界進行對齊。這個可能會降低壓縮算法的效率,只用于必要的時候。
Z_FINISH:輸入和待輸出的數據都被處理完,則返回 Z_STREAM_END。如果返回 Z_OK or Z_BUF_ERROR 則需要再次調用 Z_FINISH 直到返回 Z_STREAM_END。
deflateEnd:資源釋放
壓縮完成后,釋放空間,僅僅釋放deflateInit 中申請的空間,自己申請的空間還是要自己釋放。

解壓函數
inflateInit :解壓初始化函數,內部調用的inflateInit2。
inflateInit2 :解壓初始化的基礎函數
infalte :解壓函數
inflateEnd :同deflateEnd作用類似
uncompress :解壓縮
解壓初始化:

strm:和deflate 一樣,初始化三個回調。
windownBits :含義和deflateInit2 一樣
解壓函數:

z_streamp : 四個參數
strm.next_in = 待解壓數據
strm.next_out = 解壓以后數據存儲的 buffer
strm.avail_in = 待解壓數據的長度
strm.avail_out = 解壓數據存儲 buffer 的長度
flush :如果是 Z_NO_FLUSH,說明還有數據沒有解壓。
如果是Z_FINISH說明這是最后一包待解壓的數據
資源釋放:

10.gzip 壓縮提升網站速度
講講對于Nginx而言,怎樣去優化。
# 開啟 gzip
gzip on
# 啟用 gzip 壓縮的最小文件,小于設置值的文件將不會壓縮
gzip_min_length 1k;
# gzip 壓縮級別,1-9,數字越大壓縮的越好,也越占用 CPU 時間,后面會有詳細說明
gzip_comp_level 1;
# 進行壓縮的文件類型。JAVAscript 有多種形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain Application/JavaScript application/x-javascript text/css application/xml
text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject
font/ttf font/opentype font/x-woff image/svg+xml;
# 是否在 http header 中添加 Vary: Accept-Encoding,建議開啟
gzip_vary on;
# 禁用 IE 6 gzip
gzip_disable "MSIE [1-6].";
#設置壓縮所需要的緩沖區大小
gzip_buffers 32 4k;
# 設置 gzip 壓縮針對的 HTTP 協議版本,沒做負載的可以不用
# gzip_http_version 1.0;
# 開啟緩存
location ~* ^.+.(ico|gif|jpg|jpeg|png)$ {
access_log off;
expires 2d;
}
location ~* ^.+.(css|js|txt|xml|swf|wav)$ {
access_log off;
expires 24h;
}
location ~* ^.+.(html|htm)$ {
expires 1h;
}
location ~* ^.+.(eot|ttf|otf|woff|svg)$ {
access_log off;
expires max;
}
# 格式
# expires 30s;
# expires 30m;
# expires 2h;
# expires 30d;
以上單獨參數的說明:
gzip on:
打開或關閉gzip
Syntax: gzip on | off;
Default: gzip off;
Context: http, server, location, if in location
gzip_buffers:
用于處理請求壓縮的緩沖區數量和大小。如32 4K表示按照內存頁為單位,建議使用默認值。
Syntax: gzip_buffers number size;
Default: gzip_buffers 32 4k|16 8k;
Context: http, server, location
gzip_comp_level
設置gzip壓縮級別,級別越低壓縮速度越快,文件壓縮比越小。反之速度越慢文件壓縮比越大。
Syntax: gzip_comp_level level;
Default: gzip_comp_level 1;
Context: http, server, location
gzip_disable
通過表達式,表明哪些 UA 頭部使用 gzip 壓縮。
Syntax: gzip_disable regex ...;
Default: —
Context: http, server, location
This directive appeared in version 0.6.23.
gzip_min_length
表示當資源大于該長度時,才進行壓縮,資源大小取響應頭中的Content-Length 進行比較,如果響應頭不存在 Content_length 信息,該限制參數對于這個響應包是不起作用的;這個值不建議設置太小,如果太小,一些本來很小的文件,經過壓縮,反而變大,建議1k起,當然也需要根據自己實際的情況來去設計。
Syntax: gzip_min_length length;
Default: gzip_min_length 20;
Context: http, server, location
gzip_http_version
識別 http 協議的版本,早期的瀏覽器不支持 gzip 壓縮,用戶會看到亂碼。默認在http1.0的協議下不開啟gzip壓縮。
Syntax: gzip_http_version 1.0 | 1.1;
Default: gzip_http_version 1.1;
Context: http, server, location
gzip_proxied
Nginx 作為反向代理的時候啟用:
off – 關閉所有的代理結果數據壓縮
expired – 如果 header 中包含 "Expires" 頭信息,啟用壓縮
no-cache – 如果 header 中包含 "Cache-Control:no-cache" 頭信息,啟用壓縮
no-store – 如果 header 中包含 "Cache-Control:no-store" 頭信息,啟用壓縮
private – 如果 header 中包含 "Cache-Control:private" 頭信息,啟用壓縮
no_last_modified – 啟用壓縮,如果 header 中包含 "Last_Modified" 頭信息,
啟用壓縮
no_etag – 啟用壓縮,如果 header 中包含 "ETag" 頭信息,啟用壓縮
auth – 啟用壓縮,如果 header 中包含 "Authorization" 頭信息,啟用壓縮
any – 無條件壓縮所有結果數據
Syntax: gzip_proxied off | expired | no-cache | no-store | private | no_last_modified
| no_etag | auth | any ...;
Default: gzip_proxied off;
Context: http, server, location
gzip_types
設置需要壓縮的 MIME 類型,如果不在設置類型范圍內的請求不進行壓縮。根據這個值進行匹配。"text/html"類型總是會被壓縮。
Syntax: gzip_types mime-type ...;
Default: gzip_types text/html;
Context: http, server, location
gzip_vary
在響應頭添加
AcceptEncoding:gzip,對于本身不支持agip壓縮的客戶端瀏覽器有用。
Syntax: gzip_vary on | off;
Default: gzip_vary off;
Context: http, server, location
本篇文章就分析到這里,歡迎點贊,收藏,分享。