使用開源庫zlib壓縮和解壓檔案
阿新 • • 發佈:2019-01-09
zlib,一個十分強大的開源壓縮解壓庫,應用示範廣泛,很多開源庫中都有它的存在(libpng,libzplay,ffmpeg……)。
作為普通開發者只要掌握其主要的兩個函式就足夠用了:
int compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
compress函式將 source 緩衝區中的內容壓縮到 dest 緩衝區。 sourceLen 表示
source 緩衝區的大小(以位元組計)。注意函式的第二個引數 destLen 是傳址呼叫。當呼叫函式時,destLen表示 dest 緩衝區的大小,destLen > (sourceLen + 12)*100.1%。
int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
uncompress 函式將 source 緩衝區的內容解壓縮到 dest 緩衝區。sourceLen 是
source 緩衝區的大小(以位元組計)。注意函式的第二個引數 destLen 是傳址呼叫。當呼叫函式時,destLen 表示 dest 緩衝區的大小, dest 緩衝區要足以容下解壓後的資料。
在進行解壓縮時,需要提前知道被壓縮的資料解壓出來會有多大。這就要求在進行壓縮之前,儲存原始資料的大小(也就是解壓後的資料的大小)。這不是 zlib 函式庫的功能,需
要我們做額外的工作。當函式退出後, destLen 是解壓出來的資料的實際大小。
看一個小例子:
/ zlibDemo.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include "zlib.h" #include <assert.h> #include <Windows.h> #include <iostream> using std::cout; using std::endl; //靜態載入如下: //#pragma comment(lib,"zlib1") const char* pFileCom="..\\Debug\\save.xml";//原始檔 const char* pFileSave="..\\Debug\\1.zip";//壓縮後的檔案 #define MAX_LEN 1024*100//本例只適用於小於100KB的檔案 int _tmain(int argc, _TCHAR* argv[]) { //壓縮檔案 FILE* fp1=NULL; fp1=fopen(pFileCom,"rb"); assert(fp1); //申請緩衝區 unsigned char* pBufferRes=new unsigned char[MAX_LEN]; unsigned char* pBufferDes=new unsigned char[MAX_LEN]; //置零 memset(pBufferRes,0,MAX_LEN); memset(pBufferDes,0,MAX_LEN); //讀取整個檔案到緩衝區 fread(pBufferRes,sizeof(unsigned char),MAX_LEN-1,fp1); uLongf lSize=strlen((const char*)pBufferRes); //動態載入DLL HINSTANCE hIns=::LoadLibrary(_T("..\\Debug\\zlib1.dll")); uLongf desLen; if(hIns) { typedef int (*fun)(Bytef*,uLongf*,const Bytef*,uLongf); fun f=NULL; //指向函式地址的指標 f=(fun)GetProcAddress(hIns,"compress"); if(f==NULL) { cout<<"獲取模組函式地址失敗!"<<endl; ::FreeLibrary(hIns); return 1; } int nError=f(pBufferDes,&desLen,pBufferRes,lSize); //desLen必須大於lsize,詳情請參照zlib文件 if(nError!=Z_OK) { cout<<"壓縮失敗!"<<endl; ::FreeLibrary(hIns); fclose(fp1); return 1; } cout<<"壓縮成功,壓縮率為: %"<<desLen/(float)lSize*100<<endl; } else { cout<<"載入庫檔案失敗!"<<endl; return 1; } fclose(fp1); FILE* fp2=NULL; fp2=fopen(pFileSave,"wb"); //將壓縮後的資訊寫入檔案 fwrite(pBufferDes,sizeof(unsigned char),desLen,fp2); fclose(fp2); ///////////////////////////////////////////////////////////////////////////////////////////////// //解壓檔案 memset(pBufferDes,0,MAX_LEN); memset(pBufferRes,0,MAX_LEN); fp1=fopen("..\\Debug\\1.zip","rb"); desLen=fread(pBufferRes,1,desLen,fp1); typedef int (*unFun)(Bytef*,uLongf*,const Bytef*,uLongf); unFun uf=NULL; uf=(unFun)GetProcAddress(hIns,"uncompress"); uLongf unSize; if(uf) { int nRet=uf(pBufferDes,&unSize,pBufferRes,desLen); ::FreeLibrary(hIns); if(nRet!=Z_OK) { cout<<"解壓縮失敗"<<endl; fclose(fp1); return 1; } } fclose(fp1); fp2=fopen("..\\Debug\\uncompress.xml","wb"); fwrite(pBufferDes,1,unSize,fp2); fclose(fp2); cout<<"成功解壓檔案"<<pFileSave<<"到uncompress.xml"<<endl;
//釋放申請的記憶體空間
delete[] pBufferDes;
pBufferDes=NULL;
delete[] pBufferRes;
pBufferRes=NULL;
return 0;
}
/*zlib中兩個主要函式的宣告:
int compress OF((Bytef *dest, uLongf *destLen,const Bytef *source, uLong sourceLen));
int uncompress OF((Bytef *dest, uLongf *destLen,const Bytef *source, uLong sourceLen));*/
執行程式,結果如下:
下載地址: