字符集編碼與資料壓縮
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)一旦資料通過緩衝區,那麼它將移動到滑動視窗中,並變成字典的一部分。滑動視窗需要預設一個定值。
(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
本篇文章就分析到這裡,歡迎點贊,收藏,分享。