1. 程式人生 > >Linux下使用zlib實現資料壓縮解壓

Linux下使用zlib實現資料壓縮解壓

1、背景

本文舉例說明了:專案過程中字串資料傳輸的場景下(檔名列表),如何使用資料壓縮減少頻寬的開銷;

2、相關知識

引用外部的一個手冊進行說明

3、實現方法

deflate壓縮實現,壓縮完成後會提示Z_STREAM_END

int gzcompress(void *data, size_t ndata, void *zdata, size_t *nzdata)
{
        int ret = -1;
        z_stream c_stream;
        if (!data || !ndata) {
                printf("NULL\n");
                return -1;
        }
        c_stream.zalloc = NULL;
        c_stream.zfree  = NULL;
        c_stream.opaque = NULL;
        if (deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
                                         MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
                printf("deflateInit2\n");
                return -1;
        }
        c_stream.next_in   = (Bytef *)data;
        c_stream.avail_in  = ndata;
        c_stream.next_out  = (Bytef *)zdata;
        c_stream.avail_out = *nzdata;
        while (c_stream.avail_in != 0 && c_stream.total_out < *nzdata) {
                if (deflate(&c_stream, Z_NO_FLUSH) != Z_OK) {
                        printf("deflate\n");
                        goto end;
                }
        }
        if (c_stream.avail_in != 0) {
                printf("%d\n", c_stream.avail_in);
                return c_stream.avail_in;
        }
        for (;;) {
                ret = deflate(&c_stream, Z_FINISH);
                if (ret == Z_STREAM_END) {
                        printf("deflate: Z_STREAM_END\n");
                        break;
                }
                else if (ret != Z_OK) {
                        printf("deflate: %d\n", ret);
                        break;
                }
        }
end:
        if (deflateEnd(&c_stream) != Z_OK) {
                printf("deflateEnd: Failure\n");
                return -1;
        }
        *nzdata = c_stream.total_out;
        return 0;
}

inflate解壓實現,注意解壓完成是返回Z_STREAM_END,遇到Z_OK需要繼續處理
int gzdecompress(void *zdata, size_t nzdata, void *data, size_t *ndata)
{
        int ret = -1;
        z_stream d_stream = {0}; /* decompression stream */
        static char dummy_head[2] = {
                0x8 + 0x7 * 0x10,
                (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
        };
        d_stream.zalloc   = NULL;
        d_stream.zfree    = NULL;
        d_stream.opaque   = NULL;
        d_stream.next_in  = (Bytef *)zdata;
        d_stream.avail_in = 0;
        d_stream.next_out = (Bytef *)data;
        if (inflateInit2(&d_stream, MAX_WBITS + 16) != Z_OK) {
                printf("inflateInit2\n");
                return -1;
        }
        while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
                d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
                ret = inflate(&d_stream, Z_NO_FLUSH);
                switch (ret) {
                case Z_OK:
                        continue;
                case Z_STREAM_END:
                        printf("inflate: Z_STREAM_END\n");
                        goto end;
                case Z_DATA_ERROR:
                        d_stream.next_in = (Bytef *)dummy_head;
                        d_stream.avail_in = sizeof(dummy_head);
                        if ((ret = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) {
                                printf("inflate failed\n");
                                goto end;
                        }
                        break;
                default:
                        printf("inflate: %d\n", ret);
                        goto end;
                }
        }
end:
        if (inflateEnd(&d_stream) != Z_OK) {
                printf("inflateEnd: Failure\n");
                return -1;
        }
        *ndata = d_stream.total_out;
        return 0;
}

測試函式如下,使用了檔案列表進行測試:
int main(int argc, char *argv[])
{
        int ret = -1;
        char input[] = (
                        "/usr/local/vim\n"
                        "/usr/local/vim/share\n"
                        "/usr/local/vim/share/vim\n"
                        "/usr/local/vim/share/vim/print\n"
                        "/usr/local/vim/share/vim/keymap\n"
                        "/usr/local/vim/share/vim/autoload\n"
                        "/usr/local/vim/share/vim/autoload/xml\n"
                        "/usr/local/vim/share/vim/indent\n"
                        "/usr/local/vim/share/vim/macros\n"
                        "/usr/local/vim/share/vim/mang/sk\n"
                        "/usr/local/vim/share/vim/lang/sk/LC_MESSAGES\n"
                        );
        char gzip[1024] = {0};
        char output[1024] = {0};
        size_t ngzip = sizeof(gzip);
        size_t nout = sizeof(output);
        assert((ret = gzcompress(input, sizeof(input), gzip, &ngzip)) == 0);
        assert((ret = gzdecompress(gzip, ngzip, output, &nout)) == 0);
        printf(" input: %zd\n%s\n", sizeof(input), input);
        printf("output: %zd\n%s\n", nout, output);
        printf("Result:\t\t\t\t[%s]\n", ret ? "Failure" : "Success");
        exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
}

執行結果如下:

deflate: Z_STREAM_END
inflate: Z_STREAM_END
 input: 339
/usr/local/vim
/usr/local/vim/share
/usr/local/vim/share/vim
/usr/local/vim/share/vim/print
/usr/local/vim/share/vim/keymap
/usr/local/vim/share/vim/autoload
/usr/local/vim/share/vim/autoload/xml
/usr/local/vim/share/vim/indent
/usr/local/vim/share/vim/macros
/usr/local/vim/share/vim/mang/sk
/usr/local/vim/share/vim/lang/sk/LC_MESSAGES

output: 339
/usr/local/vim
/usr/local/vim/share
/usr/local/vim/share/vim
/usr/local/vim/share/vim/print
/usr/local/vim/share/vim/keymap
/usr/local/vim/share/vim/autoload
/usr/local/vim/share/vim/autoload/xml
/usr/local/vim/share/vim/indent
/usr/local/vim/share/vim/macros
/usr/local/vim/share/vim/mang/sk
/usr/local/vim/share/vim/lang/sk/LC_MESSAGES

Result:                         [Success]
4、結論

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

以上例子通過一次性將字串資料壓縮轉換成資料流形式,在工程中實踐的意義就是犧牲CPU計算換取頻寬的方法;


相關推薦

Linux使用zlib實現資料壓縮

1、背景 本文舉例說明了:專案過程中字串資料傳輸的場景下(檔名列表),如何使用資料壓縮減少頻寬的開銷; 2、相關知識 引用外部的一個手冊進行說明 3、實現方法 deflate壓縮實現,壓縮完成後會提示Z_STREAM_END int gzcompress(void *d

linux安裝配置jdk(版)

生效 測試 linu 文件 info img url www 技術 在linux下登錄oracle官網,下載解壓版jdk 傳送門 系統默認下載到“下載”目錄中 創建要將該文件解壓的文件夾: 其中 -p 參數代表遞歸創建文件夾(可以創建多級目錄) 進

Linux 解決Tomcat8不自動war包

之前買了阿里雲伺服器後配置好了jdk,Tomcat,mysql等。然後就想當然的將專案打成war包,直接拖到Tomcat的webapps下,但無論怎麼重啟專案就是不自動解壓,後來查了各方面資料,刪除這個檔案那個檔案的,差點把Tomcat搞崩潰了也沒找到原因,最後看到講一個將Tomcat裡

linuxOracle實現資料的自動備份

由於近期工作的原因,要做一個簡單的oracle資料自動備份,因為是一個單體應用,所以就利用了linux的定時任務和oracle的exp進行資料備份,如果有不足和需要改正的地方,歡迎各位高手指正,不勝感

Linux中使用gzip來壓縮/ *.gz檔案

gzip 是linux中常見的壓縮/解壓工具,最常見的使用物件是*.gz格式的檔案,這裡簡單介紹下它最常見的用法, GZIP(1) General Commands Manual GZIP(1)NAME      gzip, gunzip, zcat - compress

unity ZIP壓縮 Byte[]資料壓縮

在網上看了一些相關資源,都比較散;為了方便以後檢視,我就整理一下 記性比較差長時間不接觸說不定就忘了  我這給一個ICSharpCode.SharpZipLib的下載連結:https://pan.baidu.com/s/1o8QcYkq 朋友們也可以百度找最新的下載一個就行

GZIP資料壓縮/工具

GZIP概念 GZIP最早由Jean-loup Gailly和Mark Adler建立,用於UNⅨ系統的檔案壓縮。我們在Linux中經常會用到字尾為.gz的檔案,它們就是GZIP格式的。現今已經成為Internet 上使用非常普遍的一種資料壓縮格式,或者說一種

linux基本操作指令,,刪除檔案操作

一般首先是安裝vmtools之後,就可以實現linux虛擬機器和主機windows的檔案的直接拖拽,這樣就會比較方便windows和linux的互動。 在指導學生做CSAPP課程實驗時,發現好多學生對基本的linux下檔案操作不能掌握,導致實驗無法順利開展,最重要的就是li

linux下載的zip檔案之後中文檔名亂碼

我在下載一些檔案的時候,我的ubunt 14.04預設按照zip檔案給我打包下載的,但是下載下來之後,發現解壓之後我的中文檔名先試試的都為亂碼,後來看了其他部落格博主的一些解決方法,發現這麼一個好的方法,親試OK的。 第一步 首先安裝7zip和convmv(如

C#實現Zip壓縮實例

bsp dll entry static empty reat lec pac 壓縮 本文只列舉一個壓縮幫助類,使用的是有要添加一個dll引用ICSharpCode.SharpZipLib.dll【下載地址】。 另外說明一下的是,這個類壓縮格式是ZIP的,所以文件的後綴寫

Linux包/打包,壓縮/命令

res file bzip2 lena dirname unzip bz2 裏的 dir .tar 解包:tar xvf FileName.tar 打包:tar cvf fileName.tar DirName tar.gz和.tgz 解壓:tar zxvf FileNam

Linux常用壓縮命令

tar  解包:tar xvf FileName.tar 打包:tar cvf FileName.tar DirName (注:tar是打包,不是壓縮!) .gz 解壓1:gunzip FileName.gz 解壓2:g

Linux常用壓縮 命令和壓縮比率對比

常用的格式有: tar, tar.gz(tgz), tar.bz2, 不同方式,壓縮和解壓方式所耗CPU時間和壓縮比率也差異也比較大。 tar 只是打包動作,相當於歸檔處理,不做壓縮;解壓也一樣,只是把歸檔檔案釋放出來。 (1)打包歸檔格式: tar -

Linux壓縮&命令

【tar命令】 解壓:tar -zxvf FileName.tar 壓縮:tar -czvf FileName.tar DirName 【gz命令】 解壓1:gunzip FileName.gz 解壓2:gzip -d FileName.gz 壓

淺談Linux各種壓縮 命令和壓縮比率對比

轉載,收藏 tar命令是linux下非常常用的命令,這篇文章對該命令介紹的比較詳細,因此轉載加收藏吧。 Linux下壓縮、解壓命令五花八門,不像在windows下一個winrar打遍天下無敵手,清一色的.rar .zip格式。比如,Linux下常用的tar tar.gz

關於linux壓縮

tar-c: 建立壓縮檔案-x:解壓-t:檢視內容-r:向壓縮歸檔檔案末尾追加檔案-u:更新原壓縮包中的檔案這五個是獨立的命令,壓縮解壓都要用到其中一個,可以和別的命令連用但只能用其中一個。下面的引數是根據需要在壓縮或解壓檔案時可選的。-z:有gzip屬性的-j:有bz2屬性

linux系統tar/gz/7z/xz/bz2/zip等各種格式的打包壓縮

linux系統下總會遇到各種格式的壓縮包,什麼tar/gz/7z/xz/bz2/zip等等,每種格式檔案的解壓和壓縮方法都不完全一致,所攜帶的引數也都各有千秋,初學者往往會一臉茫然,不知如何是好。於是,本文就對上述各種常見的檔案和命令進行一番總結和對比,以便查閱

Linux檔案壓縮

對於剛剛接觸Linux的人來說,一定會給Linux下一大堆各式各樣的檔名給搞暈。別個不說,單單就壓縮檔案為例,我們知道在Windows下最常見的壓縮檔案就只有兩種,一是,zip,另一個是.rap。可是Linux就不同了,它有.gz、.tar.gz、tgz、bz2、.Z、.ta

Qt實現zip壓縮和解,編譯、呼叫zlib和QuaZip動態庫過程詳

http://blog.csdn.net/qq_37354286/article/details/78858788之前有個小專案中需要對zip壓縮檔案進行壓縮和解壓操作,需要用到zlib庫,使用Qt開發的話可以用到已經封裝好的QuaZip。作為一枚新人程式設計師應有的習慣,我

linux壓縮

獨立 表示 屬性 末尾 jpg 一個 並且 輸出 中一 tar -c: 建立壓縮檔案-x:解壓-t:查看內容-r:向壓縮歸檔文件末尾追加文件-u:更新原壓縮包中的文件 這五個是獨立的命令,壓縮解壓都要用到其中一個,可以和別的命令連用但只能用其中一個。下面的參數是根據需要