在 IBM Bluemix 云平臺(tái)上開發(fā)并部署您的下一個(gè)應(yīng)用,。 現(xiàn)在就開始免費(fèi)試用 關(guān)于 XZ UtilsXZ Utils 是為 POSIX 平臺(tái)開發(fā)具有高壓縮率的工具,。它使用 LZMA2 壓縮算法,,生成的壓縮文件比 POSIX 平臺(tái)傳統(tǒng)使用的 gzip,、bzip2 生成的壓縮文件更小,,而且解壓縮速度也很快。最初 XZ Utils 的是基于 LZMA-SDK 開發(fā),,但是 LZMA-SDK 包含了一些 WINDOWS 平臺(tái)的特性,,所以 XZ Utils 為以適應(yīng) POSIX 平臺(tái)作了大幅的修改。XZ Utils 的出現(xiàn)也是為了取代 POSIX 系統(tǒng)中舊的 LZMA Utils,。 XZ Utils 主要包含了下列部分:
xz 文件格式XZ Utils 工具生成的壓縮文件擴(kuò)展名為 .xz (MIME 類型為"application/x-xz"),。.xz 文件格式具有下列特點(diǎn): 基于數(shù)據(jù)流: 易于通過(guò)管道 (pipe) 生成壓縮文件或解壓縮文件。.xz 文件格式與 .gz/.bz2 文件一樣,,不具備對(duì)多個(gè)文件進(jìn)行歸檔打包的能力,。若要處理多個(gè)文件,可以和歸檔工具 tar 結(jié)合使用,,生成擴(kuò)展名為 .tar.xz 或 .txz 的壓縮文件,。 隨機(jī)讀取: 存儲(chǔ)的數(shù)據(jù)被劃分為獨(dú)立的壓縮塊,并對(duì)每個(gè)壓縮塊進(jìn)行索引,,當(dāng)每個(gè)壓縮塊比較小時(shí),,便能夠進(jìn)行有限的隨機(jī)讀取壓縮數(shù)據(jù)。 完整性驗(yàn)證: 可以使用 CRC32,、CRC64,、SHA-256 來(lái)進(jìn)行數(shù)據(jù)的完整性驗(yàn)證,也可以增加自定義驗(yàn)證方法,。 可連接(concatenation): 類似于 .gz/.bz2 文件,,可以把多個(gè)壓縮數(shù)據(jù)流連接到一個(gè)文件中。解壓縮時(shí),,就像解壓一個(gè)正常單壓縮流文件一樣,。 支持多filter和filter鏈: 提供自定義 filter 的能力,也能夠?qū)⒍鄠€(gè) filter 組成 filter 鏈,,對(duì)數(shù)據(jù)進(jìn)行處理,。這點(diǎn)與 Unix 命令間使用的管道 (pipe) 類似。 可填充(padding): 可以在 .xz 文件末尾填充二進(jìn)制'0'以充滿特定大小的空間,,比如備份磁帶上的一個(gè)塊 (block),。 LZMA2 壓縮算法LZMA2 是 .xz 文件格式使用的壓縮算算法。LZMA(Lempel-Ziv-Markov chain-Algorithm) 原本是 Windows 平臺(tái)上著名壓縮工具 7-Zip 中的 .7z 文件格式的默認(rèn)壓縮算法,。LZMA 使用類似于 LZ77 的字典編碼機(jī)制,。在大多數(shù)情況下,,LZMA 算法都能夠提供很高壓縮率和較快的壓縮速度。LZMA2 是 LZMA 的改進(jìn)版本,,相對(duì)于 LZMA,,LZMA2 增進(jìn)了 encoder 和 decoder 的實(shí)現(xiàn),并改善了對(duì)多線程的支持,。 高壓縮率與 POSIX 系統(tǒng)上傳統(tǒng)的壓縮工具 gzip,、bzip2 相比,XZ Utils 吸引人的地方在于,,它能夠提供更高的壓縮率,,生成的文件更小,而且解壓數(shù)據(jù)的速度也很快,。XZ Utils 的主頁(yè)上描述:對(duì)于典型文件,,XZ Utils 能夠生成比使用 gzip 小 30%,,比使用 bzip 小 15% 的壓縮文件,。 下面便針對(duì)壓縮率、壓縮速度和解壓速度三個(gè)方面進(jìn)行簡(jiǎn)單的驗(yàn)證,。 測(cè)試環(huán)境的 CPU 為 AMD Athlon X4 3.0GHz,,內(nèi)存為 8G。操作系統(tǒng)為 64 位版本的 Gentoo Linux,。所有的測(cè)試均在 /dev/shm(即內(nèi)存設(shè)備)下進(jìn)行,,這樣盡可能避免了 I/O 讀寫對(duì)測(cè)試結(jié)果的影響。 測(cè)試內(nèi)容為 gzip,、bzip2,、xz 分別壓縮原始大小為 445M 的 linux-kernel-3.2.1.tar 文件,然后解壓縮生成的壓縮文件,。測(cè)試分兩組:
分別記錄下生成的壓縮文件大小,壓縮用時(shí),,解壓用時(shí)數(shù)據(jù),。將所有收集到的數(shù)據(jù)進(jìn)行整理。 處理后,,使用 gnuplot 工具分別生成了下面的三個(gè)柱狀比較圖,。下列柱狀圖中 X 軸的 "-" 表示使用默認(rèn)壓縮率。 壓縮后文件大小的比較如下圖: 圖 1. 壓縮后文件大小比較根據(jù)上圖,,清楚地顯示 xz 生成的壓縮文件最小,,即具有高壓縮率,。且通過(guò)圖中比較可以看出,xz 生成的壓縮文件大小的確約比 gzip 生成的文件小 30%,,比 bzip 生成的文件小 15%,。 壓縮用時(shí)的比較如下圖: 圖 2. 壓縮用時(shí)數(shù)據(jù)比較:由此圖可以看到 xz 隨著壓縮率的升高,所用壓縮時(shí)間也會(huì)隨之增長(zhǎng),。且相對(duì)于 gzip/bzip2 所用時(shí)間大幅增加,。在對(duì)壓縮時(shí)間要求相對(duì)苛刻的場(chǎng)合,并不推薦使用 XZ Utils,。 解壓縮用時(shí)的比較如下圖: 圖 3. 解壓縮用時(shí)數(shù)據(jù)比較:由此圖可以看到 xz 的解壓速度和 gzip 一樣有著穩(wěn)定的表現(xiàn),。大幅少于 bzip2 的解壓縮用時(shí),雖比 gzip 用時(shí)稍多,,但從 xz Utils 在同等條件下比 gzip 擁有更出色高壓縮率來(lái)看,,解壓縮用時(shí)的表現(xiàn)也是不錯(cuò)的。 從以上的驗(yàn)證數(shù)據(jù)的對(duì)比可以看出:XZ Utils 具有 高壓縮率,解壓速度快的特點(diǎn),。能夠生成更小文件的同時(shí),,也能提供穩(wěn)定快速的解壓,在對(duì) 數(shù)據(jù)大小比較敏感的場(chǎng)合,,比如說(shuō)大數(shù)據(jù)的網(wǎng)絡(luò)傳輸,,文件的備份,處理能力有限的嵌入系統(tǒng)等場(chǎng)合,,有著十分廣泛的用途,。 回頁(yè)首 使用 xz 命令xz 命令的基本用法
復(fù)雜的用法
從上面執(zhí)行結(jié)果來(lái)看,,利用合適的 filter Chain 最終生成的文件大小為 865KB。參數(shù) --x86 --lzma2 就組成了一個(gè) filter Chain,。參數(shù) --x86 是指使用 x86 平臺(tái)的 BCJ filter,,適用于 32 位和 64 位系統(tǒng)。參數(shù) --lzma2 則指使用 lzma2 算法進(jìn)行壓縮,。 回頁(yè)首 使用 xzgrep,xzcat,xzdiff 等實(shí)用工具xzcatxzcat 命令其相當(dāng)于 "xz --decompress --stdout" 就是將解壓出的數(shù)據(jù)輸出到標(biāo)準(zhǔn)輸出 (stdout),。下面的例子用來(lái)統(tǒng)計(jì)壓縮 test.txt.xz 文件所包含數(shù)據(jù)的行數(shù),。 $ xzcat test.txt.xz | wc -l ## count the lines of test.txt xzgrepxzgrep 可以用來(lái) grep 壓縮文件所包含的數(shù)據(jù)內(nèi)容。其內(nèi)部就是調(diào)用 grep 命令,,所以參數(shù)和 grep 一致,。下面的例子打印出 xz_pipe_comp_mini.c.xz 中所有包含以"lzma_"開頭單詞的行號(hào)和行內(nèi)容。例: $ xzgrep -P -n "lzma_\w+" xz_pipe_comp_mini.c.xz 8: lzma_check check = LZMA_CHECK_CRC64; 9: lzma_stream strm = LZMA_STREAM_INIT; /* alloc and init lzma_stream struct */ 15: lzma_easy_encoder (&strm, 6, LZMA_CHECK_CRC64); 28: lzma_action action = in_finished ? LZMA_FINISH : LZMA_RUN; 35: lzma_code (&strm, action); /* compress data */ 42: lzma_end (&strm); xzless 和 xzmore這兩個(gè)命令可以分頁(yè)查看壓縮文件中的內(nèi)容,。簡(jiǎn)單的來(lái)說(shuō),,相當(dāng)于 "xzcat <file.xz> | less" 或 "xzcat <file.xz> | more" xzdiff 和 xzcmp這兩個(gè)命令用于比較兩個(gè) .xz 文件。內(nèi)部分別調(diào)用命令 diff 和 cmp 來(lái)實(shí)現(xiàn)文件內(nèi)容的比較,。例: $ xzdiff xz_pipe_comp_mini.c.orig.xz xz_pipe_comp_mini.c.xz 20c20 < if (feof (in_file)) --- > if (feof (in_file)) { 21a22 > } $ 回頁(yè)首 liblzma API關(guān)于 liblzma APIliblzma API 提供了 LZMA1/LZMA2 算法的實(shí)現(xiàn),,并具有類似于 Zlib 的 API 接口。也和 gzip,、bzip2 一樣 XZ Utils 是流壓縮格式,。通過(guò) liblzma API 接口,可以相對(duì)簡(jiǎn)單的編程實(shí)現(xiàn)對(duì)數(shù)據(jù)的壓縮和解壓縮,。 使用 liblzma API 壓縮數(shù)據(jù)使用 liblzma 壓縮數(shù)據(jù)的過(guò)程,,大致過(guò)程如下。
下面是一段完整的示例程序。所示程序從標(biāo)準(zhǔn)輸入 (stdin) 讀入數(shù)據(jù),,壓縮后寫到標(biāo)準(zhǔn)輸出 (stdout). 為了更便于理解壓縮過(guò)程,,示例代碼省略了所有的異常處理和一些其他次要細(xì)節(jié)。 清單 1. 壓縮數(shù)據(jù)的代碼示例#include <stdio.h> #include <stdint.h> #include <inttypes.h> #include <stdbool.h> #include <lzma.h> void xz_compress (FILE *in_file, FILE *out_file) { lzma_check check = LZMA_CHECK_CRC64; /* alloc and init lzma_stream struct */ lzma_stream strm = LZMA_STREAM_INIT; uint8_t in_buf [4096]; uint8_t out_buf [4096]; bool in_finished = false; /* initialize xz encoder */ lzma_easy_encoder (&strm, 6, LZMA_CHECK_CRC64); while (! in_finished) { /* read incoming data */ size_t in_len = fread (in_buf, 1, 4096, in_file); if (feof (in_file)) { in_finished = true; } strm.next_in = in_buf; strm.avail_in = in_len; /* if no more data from in_buf, flushes the internal xz buffers and * closes the xz data with LZMA_FINISH */ lzma_action action = in_finished ? LZMA_FINISH : LZMA_RUN; /* loop until there's no pending compressed output */ do { strm.next_out = out_buf; strm.avail_out = 4096; lzma_code (&strm, action); /* compress data */ size_t out_len = 4096 - strm.avail_out; fwrite (out_buf, 1, out_len, out_file); /* write compressed data */ }while (strm.avail_out == 0); } lzma_end (&strm); } int main () { xz_compress (stdin, stdout); return 0; } 編譯命令 : $ gcc -g -o xz_pipe_mini xz_pipe_comp_mini.c -llzma 使用例子 : $ cat a.txt | xz_pipe_mini > a.txt.xz 使用 liblzma API 解壓數(shù)據(jù)使用 liblzma 進(jìn)行解壓縮的過(guò)程和壓縮數(shù)據(jù)的過(guò)程基本一致,。主要的區(qū)別是使用 lzma_stream_decoder 函數(shù)代替 lzma_easy_decoder 函數(shù)來(lái)進(jìn)行 decoder 的初始化,。 lzma_stream_decoder (&strm, memory_limit, flags); lzma_stream_decoder 函數(shù)的第一參數(shù)是數(shù)是 lzma_stream 結(jié)構(gòu)體變量的指針。第二參數(shù)則指明了在解壓縮過(guò)程中使用內(nèi)存的最大值,。若 UINT64_MAX 則為不限制內(nèi)存使用量,。第三參數(shù)用來(lái)指明一些其他 flags 值:
下面是一段完整的示例程序,。所示程序從標(biāo)準(zhǔn)輸入 (stdin) 讀入數(shù)據(jù),解壓縮的數(shù)據(jù)寫到標(biāo)準(zhǔn)輸出 (stdout). 示例代碼省略了所有的異常處理和一些其他次要細(xì)節(jié),。 清單 2. 解壓縮數(shù)據(jù)的代碼示例#include <stdio.h> #include <stdint.h> #include <inttypes.h> #include <stdbool.h> #include <lzma.h> #define IN_BUF_MAX 4096 #define OUT_BUF_MAX 4096 #define RET_OK 0 #define RET_ERROR 1 int xz_decompress (FILE *in_file, FILE *out_file) { /* alloc and init lzma_stream struct */ lzma_stream strm = LZMA_STREAM_INIT; uint8_t in_buf [IN_BUF_MAX]; uint8_t out_buf [OUT_BUF_MAX]; bool in_finished = false; bool out_finished = false; lzma_action action; lzma_ret ret_xz; int ret; ret = RET_OK; /* initialize xz decoder */ ret_xz = lzma_stream_decoder (&strm, UINT64_MAX, LZMA_TELL_UNSUPPORTED_CHECK|LZMA_CONCATENATED ); if (ret_xz != LZMA_OK) return RET_ERROR; while ((! in_finished) && (! out_finished)) { /* read incoming data */ size_t in_len = fread (in_buf, 1, IN_BUF_MAX, in_file); if (feof (in_file)) in_finished = true; strm.next_in = in_buf; strm.avail_in = in_len; /* if no more data from in_buf, flushes the internal xz buffers and closes the decompressed data with LZMA_FINISH */ action = in_finished ? LZMA_FINISH : LZMA_RUN; /* loop until there's no pending decompressed output */ do { /* out_buf is clean at this point */ strm.next_out = out_buf; strm.avail_out = OUT_BUF_MAX; /* decompress data */ ret_xz = lzma_code (&strm, action); if ((ret_xz != LZMA_OK) && (ret_xz != LZMA_STREAM_END)) { out_finished = true; ret = RET_ERROR; } else { /* write decompressed data */ size_t out_len = OUT_BUF_MAX - strm.avail_out; fwrite (out_buf, 1, out_len, out_file); if (ferror (out_file)) { out_finished = true; ret = RET_ERROR; } } } while (strm.avail_out == 0); } lzma_end (&strm); return ret; } int main () { return xz_decompress (stdin, stdout); } 編譯命令: $ gcc -g -o xz_pipe_decomp_mini xz_pipe_decomp_mini.c -llzma 使用例子: $ cat a.txt.xz | xz_pipe_decomp_mini > a.txt 回頁(yè)首 結(jié)束語(yǔ)本文著重從實(shí)用的角度介紹了 XZ Utils 的主要部分,,還有一些內(nèi)容由于篇幅的原因,沒有提及,。如果您想更深入的研究 XZ Utils,,可以訪問(wèn) XZ Utils 的官方網(wǎng)站,那里可以找到最新的源代碼和更詳盡的文檔,。 |
|
來(lái)自: dwlinux_gs > 《Linux壓縮率比較》