Zlib實現壓縮和解壓縮流程

壓縮流程: html

1.使用zlib作壓縮,先調用deflateInit(),這個函數必須在使用deflate以前,zalloc,zfree和opaque等字段都是在deflateInit被初始化的,deflateInit將分配按照順序分配內存空間,每次分配256K

2.deflateInit有-1 到 9的幾個壓縮級別,低壓縮級別能夠得到更快的執行,可是壓縮比例低,Z_DEFAULT_COMPRESSION爲-1,平衡壓縮比例與 速度能夠把Level設爲6,Level 0實際上沒有壓縮.另外你也能夠使用deflateInit2()來代替DeflateInit().

3.設計一個循環壓縮數據,裏面只掉用一次deflate(),而且在循環末尾檢測是否到達文件底部.

4.讀入文件,讀入的byte量放到avail_in裏面,next_in存放指向這些的字節的指針,使用feof()檢測是否到底,爲了防止發生任何內存泄漏,請使用delateEnd()

5.內部循環將咱們讀入的數據壓縮,當沒有數據能夠壓縮的時候,avail_in裏面的值爲0.

6.avail_out指向壓縮數據量大小,next_out指向壓縮的數據

7.調用deflate(),該函數第二個參數若是爲Z_NO_FLUSH的時候數據處於壓縮狀態,一但爲Z_FINISH,deflate()將把壓縮數據傳到輸出流,deflate的返回值爲Z_OK和Z_STREAM_END是正確的

解壓縮流程:
1.初始化z_stream與壓縮過程相同,可是不用設定壓縮level,avail_in和next_in須要在inflateInit()以前初始化
2.讀入數據填充strm結構,若是到達文件尾跳出外圍循環並報告一個Error
3.內層循環實現與壓縮相同的功能,將全部輸入數據解壓成輸出數據

4.調用inflate()函數,這裏不須要調整flush參數,但要注意inflate的返回值. app

#include "zconf.h"
#include "zlib.h"
#include <string.h>
// The one and only application object
CWinApp theApp ;
using namespace std ;
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
#  include <fcntl.h>
#  include <io.h>
#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
#else
#  define SET_BINARY_MODE(file)
#endif
#define CHUNK 16384
int def(FILE*source,FILE*dest,int level)
{
    int ret,flush ;
    unsigned have ;
    z_stream strm ;
    unsigned char in[CHUNK];
    unsigned char out[CHUNK];
    /*allocate defalte state*/
    strm.zalloc=Z_NULL ;
    strm.zfree=Z_NULL ;
    strm.opaque=Z_NULL ;
    ret=deflateInit(&strm,level);
    if(ret!=Z_OK)
    return ret ;
    
    do 
    {
        strm.avail_in=fread(in,1,CHUNK,source);
        if(ferror(source))
        {
            (void)deflateEnd(&strm);
            return Z_ERRNO ;
        }
        flush=feof(source)?Z_FINISH:Z_NO_FLUSH ;
        strm.next_in=in ;
        do 
        {
            strm.avail_out=CHUNK ;
            strm.next_out=out ;
            ret=deflate(&strm,flush);
            have=CHUNK-strm.avail_out ;
            if(fwrite(out,1,have,dest)!=have||ferror(dest))
            {
                (void)deflateEnd(&strm);
                return Z_ERRNO ;
            }
            //The way we tell that deflate() has no more output is by seeing that it did not fill the output
            buffer,
            //leaving avail_out greater than zero.
        }
        while(strm.avail_out==0);
    }
    while(flush!=Z_FINISH);
    (void)deflateEnd(&strm);
    return Z_OK ;
}
int inf(FILE*source,FILE*dest)
{
    int ret ;
    unsigned have ;
    z_stream strm ;
    unsigned char in[CHUNK];
    unsigned char out[CHUNK];
    strm.zalloc=Z_NULL ;
    strm.zfree=Z_NULL ;
    strm.opaque=Z_NULL ;
    strm.avail_in=0 ;
    strm.next_in=Z_NULL ;
    ret=inflateInit(&strm);
    if(ret!=Z_OK)
    return ret ;
    do 
    {
        strm.avail_in=fread(in,1,CHUNK,source);
        if(ferror(source))
        {
            (void)inflateEnd(&strm);
            return Z_ERRNO ;
        }
        if(0==strm.avail_in)
        break ;
        strm.next_in=in ;
        do 
        {
            strm.avail_out=CHUNK ;
            strm.next_out=out ;
            ret=inflate(&strm,Z_NO_FLUSH);
            switch(ret)
            {
                case Z_NEED_DICT :
                ret=Z_DATA_ERROR ;
                case Z_DATA_ERROR :
                case Z_MEM_ERROR :
                (void)inflateEnd(&strm);
                return ret ;
            }
            have=CHUNK-strm.avail_out ;
            if(fwrite(out,1,have,dest)!=have||ferror(dest))
            {
                (void)inflateEnd(&strm);
                return Z_ERRNO ;
            }
        }
        while(strm.avail_out==0);
    }
    while(ret!=Z_STREAM_END);
    (void)inflateEnd(&strm);
    return ret=Z_STREAM_END?Z_OK:Z_DATA_ERROR ;
}
void zerr(int ret)
{
    fputs("zpipe: ",stderr);
    switch(ret)
    {
        case Z_ERRNO :
        if(ferror(stdin))
        fputs("error reading stdin/n",stderr);
        if(ferror(stdout))
        fputs("error writing stdout/n",stderr);
        break ;
        case Z_STREAM_ERROR :
        fputs("invalid compression level/n",stderr);
        break ;
        case Z_DATA_ERROR :
        fputs("invalid or incomplete deflate data/n",stderr);
        break ;
        case Z_MEM_ERROR :
        fputs("out of memory/n",stderr);
        break ;
        case Z_VERSION_ERROR :
        fputs("zlib version mismatch!/n",stderr);
    }
}
int _tmain(int argc,TCHAR*argv[],TCHAR*envp[])
{
    int nRetCode=0 ;
    // initialize MFC and print and error on failure
    if(!AfxWinInit(:: GetModuleHandle(NULL),NULL,:: GetCommandLine(),0))
    {
        // TODO: change error code to suit your needs
        _tprintf(_T("Fatal Error: MFC initialization failed/n"));
        nRetCode=1 ;
    }
    else 
    {
        // TODO: code your application's behavior here.
    }
    int ret ;
    SET_BINARY_MODE(stdin);
    SET_BINARY_MODE(stdout);
    if(argc==1)
    {
        ret=def(stdin,stdout,Z_DEFAULT_COMPRESSION);
        if(ret!=Z_OK)
        zerr(ret);
        return ret ;
    }
    else if(argc==2&&strcmp(argv[1],"-d")==0)
    {
        ret=inf(stdin,stdout);
        if(ret!=Z_OK)
        zerr(ret);
        return ret ;
    }
    else 
    {
        fputs("zpipe usage: zpipe [-d] < source > dest/n",stderr);
    }
    return nRetCode ;
}
Zlib的deflate, z_stream結構的使用
 
使用deflate進行壓縮時,先要定義z_stream結構體,
先將z_stream的zalloc, zfree, opaque偏量設爲Z_NULL, 再調用
deflateInit函數初始化z_stream結構,初始化時主要是用z_stream結構與Z_DEFAULT_COMPRESSION和默認壓縮來初始化,
 
初始化好後,再要初始化四個重要份量,爲被壓縮源字符串next_in,被壓源字符串的長度avail_in,壓縮後字符串的最大長度(avail_out),壓縮後字符串的存放緩衝區(next_out)。
 
     設好後,還得設一個參數即刷新方式flush, 這個參數是deflate函數的第二個參數,通常設爲Z_FINISH, 或者Z_NO_FLUSH, 若是是讀的文件取字符串
能夠使用flush = feof(source) ? Z_FINISH : Z_NO_FLUSH再設定。
 
    以z_stream, flush爲參數,調用deflate函數後,這時開始的next_out指向的內存中就有壓縮的字符串了,但next_out, avail_out都會發生變化,其具體的變化是,avail_out會變爲剩下的尚未使用的最大空間數,而next_out是指的原來的原來的指針加上所讀的字符串,
 
壓縮後,能夠經過最大壓縮後因此空間大小減avail_out得壓縮後串大小,經過原來的壓縮串指針得壓縮後字符串。
若是有任何錯誤,調用deflateEnd函數,當avail_out等於零時,表示加密串滿了,則還要壓,不過通常不可能由於壓縮串不可能大於源串,若是加密串沒滿,那麼,確認一下avail_in是否爲0, 表示把源串全壓了,再經過flush的值判斷是否再壓。
 

以上完成了一次壓縮 函數

更多細節:http://www.zlib.net/zlib_how.html ui

相關文章
相關標籤/搜索