原文鏈接: http://www.cnblogs.com/fairycao/archive/2009/12/09/1620414.html
開源代碼:http://www.zlib.net/
zlib使用手冊:http://www.zlib.net/manual.html
zlib wince版:http://www.tenik.co.jp/~adachi/wince/
在這里,你可以查看基於各種操作系統平台的壓縮與解縮代碼實現。
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
以下是經過測試的 WinCE 及 WinXP 下的代碼
<<<<<<<<
第一步: 首先到http://www.zlib.net/下載個ZLIB,
WinXP: 解壓縮后打開zlib-1.2.3\projects\visualc6\zlib.dsw,選擇Win32 LIB Release 按F7編繹生成zlib.lib, zlib.dll.
WinCE: 下載一個for Windows CE 版的包,里面針對各種平台(ARM4, ARM4I, MIPS, X86)有對應的zlibce.dll zlibce.lib.
<<<<<<<<
第二步: 建立EVC 或者 VS2005 的對話框工程.
在工程中添加以下文件:zlib.h, zconf.h, zlib.lib, zlib.dll (或者 zlibce.dll);
這3個文件就在剛才從http://www.zlib.net/下載的軟件包中.
<<<<<<<<
第三步: 包含頭文件
#include "zlib.h"
主要使用fopen等C標准接口實現的,只用到zlib的Compress()和UnCompress()接口;里面的條件編譯是針對PC和WCE的
封裝的類:
class CZlib
{
public:
CZlib();
~ CZlib();
int Compress(char * DestName,const char *SrcName);
int UnCompress(char * DestName,const char *SrcName);
};
接口實現:
壓縮
int CZlib::Compress(char * DestName,const char *SrcName) { char SourceBuffer[102400] = {0}; //壓縮文件時的源buffer FILE* fp; //打開欲壓縮文件時文件的指針 FILE* fp1; //創建壓縮文件時的指針 errno_t err; //錯誤變量的定義 #ifdef WINDOWS_PLATFORM err = fopen_s(&fp,SrcName,"r+b");//打開欲壓縮的文件 if(err) { printf("文件打開失敗! \n"); return 1; } #endif #ifdef WINDOWS_CE_PLATFORM fp = fopen_s(SrcName,"r+b");//打開欲壓縮的文件 if(fp) { printf("文件打開失敗! \n"); return 1; } #endif //獲取文件長度 long cur = ftell(fp); fseek(fp,0L,SEEK_END); long fileLength = ftell(fp); fseek(fp,cur,SEEK_SET); //讀取文件到buffer fread(SourceBuffer,fileLength,1,fp); fclose(fp); //壓縮buffer中的數據 uLongf SourceBufferLen=102400; char* DestBuffer=(char*)::calloc((uInt)SourceBufferLen, 1); err=compress((Bytef*)DestBuffer,(uLongf*)&SourceBufferLen,(const Bytef*)SourceBuffer,(uLongf)fileLength); if(err!=Z_OK) { cout<<"壓縮失敗:"<<err<<endl; return 1; } //創建一個文件用來寫入壓縮后的數據 err = fopen_s(&fp1, DestName,"w+b"); if(!fp1) { printf("壓縮文件創建失敗! \n"); return 1 ; } fwrite(DestBuffer,SourceBufferLen,1,fp1); fclose(fp1); return 0; }
解壓
int CZlib::UnCompress(char * DestName,const char *SrcName) { char uSorceBuffer[102400] = {0}; //解壓縮文件時的源buffer FILE* fp3; //打開欲解壓文件的文件指針 FILE* fp4; //創建解壓文件的文件指針 errno_t err; //錯誤變量的定義 //打開欲解壓的文件 err = fopen_s(&fp3,SrcName,"r+b"); if(err) { printf("文件打開失敗! \n"); return 1; } //獲取欲解壓文件的大小 long ucur = ftell(fp3); fseek(fp3,0L,SEEK_END); long ufileLength = ftell(fp3); fseek(fp3,ucur,SEEK_SET); //讀取文件到buffer fread(uSorceBuffer,ufileLength,1,fp3); fclose(fp3); uLongf uDestBufferLen=1024000;//此處長度需要足夠大以容納解壓縮后數據 char* uDestBuffer=(char*)::calloc((uInt)uDestBufferLen, 1); //解壓縮buffer中的數據 err=uncompress((Bytef*)uDestBuffer,(uLongf*)&uDestBufferLen,(Bytef*)uSorceBuffer,(uLongf)ufileLength); if(err!=Z_OK) { cout<<"解壓縮失敗:"<<err<<endl; return 1; } //創建一個文件用來寫入解壓縮后的數據 err = fopen_s(&fp4,DestName,"wb"); if(err) { printf("解壓縮文件創建失敗! \n"); return 1 ; } printf("寫入數據... \n"); fwrite(uDestBuffer,uDestBufferLen,1,fp4); fclose(fp4); return 0; }
測試代碼:
test.Compress("1.zip","test.docx");
test.UnCompress("11.docx","1.zip");
上述代碼對於大文件就不適合了,因為是一次讀出,一次寫入的,下面是針對大文件的改進,分批讀,分批寫,代碼如下:
WF_Error CZlib::Compress(const char * DestName,const char *SrcName) { FILE * fp_in = NULL;int len = 0;char buf[16384]; WF_Error re = WF_OK; if( NULL == (fp_in = fopen(SrcName,"rb"))) { return WF_FAIL; } ///////////////////////////////////////////// gzFile out = gzopen(DestName,"wb6f"); if(out == NULL) { return WF_FAIL; } for(;;) { len = fread(buf,1,sizeof(buf),fp_in); if(ferror(fp_in)) { re = WF_FAIL; break; } if(len == 0) break; if(gzwrite(out, buf, (unsigned)len) != len) { re = WF_FAIL; } } gzclose(out); fclose(fp_in); return re; } WF_Error CZlib::UnCompress(const char * DestName,const char *SrcName) { FILE * fp_out = NULL;WF_Error re = WF_OK; gzFile in;int len = 0;char buf[16384]; in = gzopen(SrcName,"rb"); if(in == NULL) { return WF_FAIL; } if(NULL == (fp_out = fopen(DestName,"wb"))) { gzclose(in); return WF_FAIL; } for (;;) { len = gzread(in,buf,sizeof(buf)); if(len < 0) { re = WF_FAIL; break; } if(len == 0) break; if(fwrite(buf,1,(unsigned)len,fp_out)!=len) { re = WF_FAIL; break; } } fclose(fp_out); gzclose(in); return re; }