Zlib⽂件压缩和解压
开源代码:
zlib使⽤⼿册:
zlib wince版:
在这⾥,你可以查看基于各种操作系统平台的压缩与解缩代码实现。
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
以下是经过测试的 WinCE 及 WinXP 下的代码
<<<<<<<<
第⼀步: ⾸先到下载个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个⽂件就在刚才从下载的软件包中.
<<<<<<<<
第三步: 包含头⽂件
#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)
{fread和fwrite的区别
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;
}