使用Zlib实现压缩和解压缩

使用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;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值