转载自:Known More
开源代码: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;
}