压缩流程:
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的返回值.
代码:
#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;
}
转帖:http://blog.163.com/cp7618@yeah/blog/static/702347772011114103910635/