您的位置:首页 > 其它

使用Zlib实现压缩和解压缩

2009-06-23 12:01 459 查看
使用Zlib实现压缩和解压缩

//All right revsered by yoki2009

//mailto:imj040144@tom.com

//微出版 www.epube.biz 相信梦想无界

压缩流程:

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: