首页 > 编程 > C++ > 正文

zlib库压缩和解压字符串STL string的实例详解

2020-05-23 13:38:20
字体:
来源:转载
供稿:网友

zlib库压缩和解压字符串STL string的实例详解

场景

1.一般在使用文本json传输数据, 数据量特别大时,传输的过程就特别耗时, 因为带宽或者socket的缓存是有限制的, 数据量越大, 传输时间就越长. 网站一般使用gzip来压缩成二进制.

说明

1.zlib库可以实现gzip和zip方式的压缩, 这里只介绍zip方式的二进制压缩, 压缩比还是比较可观的, 一般写客户端程序已足够.

2.修改了一下zpipe.c的实现, 其实就是把读文件改为读字符串, 写文件改为写字符串即可.

例子

// test_zlib.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <string>#include <iostream>#include <memory>#include <assert.h>#include "zlib.h"// E:/software/Lib/compress/zlib-1.2.5/src/examples// zpipe.c#define CHUNK 16384/* Compress from file source to file dest until EOF on source.  def() returns Z_OK on success, Z_MEM_ERROR if memory could not be  allocated for processing, Z_STREAM_ERROR if an invalid compression  level is supplied, Z_VERSION_ERROR if the version of zlib.h and the  version of the library linked do not match, or Z_ERRNO if there is  an error reading or writing the files. */int CompressString(const char* in_str,size_t in_len,  std::string& out_str, int level){  if(!in_str)    return Z_DATA_ERROR;  int ret, flush;  unsigned have;  z_stream strm;  unsigned char out[CHUNK];  /* allocate deflate state */  strm.zalloc = Z_NULL;  strm.zfree = Z_NULL;  strm.opaque = Z_NULL;  ret = deflateInit(&strm, level);  if (ret != Z_OK)    return ret;  std::shared_ptr<z_stream> sp_strm(&strm,[](z_stream* strm){     (void)deflateEnd(strm);  });  const char* end = in_str+in_len;  size_t pos_index = 0;  size_t distance = 0;  /* compress until end of file */  do {    distance = end - in_str;    strm.avail_in = (distance>=CHUNK)?CHUNK:distance;    strm.next_in = (Bytef*)in_str;    // next pos    in_str+= strm.avail_in;    flush = (in_str == end) ? Z_FINISH : Z_NO_FLUSH;    /* run deflate() on input until output buffer not full, finish      compression if all of source has been read in */    do {      strm.avail_out = CHUNK;      strm.next_out = out;      ret = deflate(&strm, flush);  /* no bad return value */      if(ret == Z_STREAM_ERROR)        break;      have = CHUNK - strm.avail_out;      out_str.append((const char*)out,have);    } while (strm.avail_out == 0);    if(strm.avail_in != 0);   /* all input will be used */      break;    /* done when last data in file processed */  } while (flush != Z_FINISH);  if(ret != Z_STREAM_END) /* stream will be complete */    return Z_STREAM_ERROR;  /* clean up and return */  return Z_OK;}/* Decompress from file source to file dest until stream ends or EOF.  inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be  allocated for processing, Z_DATA_ERROR if the deflate data is  invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and  the version of the library linked do not match, or Z_ERRNO if there  is an error reading or writing the files. */int DecompressString(const char* in_str,size_t in_len, std::string& out_str){  if(!in_str)    return Z_DATA_ERROR;  int ret;  unsigned have;  z_stream strm;  unsigned char out[CHUNK];  /* allocate inflate state */  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;  std::shared_ptr<z_stream> sp_strm(&strm,[](z_stream* strm){     (void)inflateEnd(strm);  });  const char* end = in_str+in_len;  size_t pos_index = 0;  size_t distance = 0;  int flush = 0;  /* decompress until deflate stream ends or end of file */  do {    distance = end - in_str;    strm.avail_in = (distance>=CHUNK)?CHUNK:distance;    strm.next_in = (Bytef*)in_str;    // next pos    in_str+= strm.avail_in;    flush = (in_str == end) ? Z_FINISH : Z_NO_FLUSH;    /* run inflate() on input until output buffer not full */    do {      strm.avail_out = CHUNK;      strm.next_out = out;      ret = inflate(&strm, Z_NO_FLUSH);      if(ret == Z_STREAM_ERROR) /* state not clobbered */        break;      switch (ret) {      case Z_NEED_DICT:        ret = Z_DATA_ERROR;   /* and fall through */      case Z_DATA_ERROR:      case Z_MEM_ERROR:        return ret;      }      have = CHUNK - strm.avail_out;      out_str.append((const char*)out,have);    } while (strm.avail_out == 0);    /* done when inflate() says it's done */  } while (flush != Z_FINISH);  /* clean up and return */  return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;}int _tmain(int argc, _TCHAR* argv[]){  const char* buf = "01010101010101010101010000000000000000000000000000011111111111111"    "01010101010101010101010000000000000000000000000000011111111111111"    "01010101010101010101010000000000000000000000000000011111111111111"    "01010101010101010101010000000000000000000000000000011111111111111"    "01010101010101010101010000000000000000000000000000011111111111111"    "01010101010101010101010000000000000000000000000000011111111111111"    "01010101010101010101010000000000000000000000000000011111111111111"    "01010101010101010101010000000000000000000000000000011111111111111"    "01010101010101010101010000000000000000000000000000011111111111111"    "01010101010101010101010000000000000000000000000000011111111111111"    "qwertyuiop[]";  std::cout << "========= CompressString ===========" << std::endl;  std::cout << "Source Buffer Size: " << strlen(buf) << std::endl;  std::string out_compress;  assert(CompressString(buf,strlen(buf),out_compress,Z_DEFAULT_COMPRESSION) == Z_OK);  std::cout << "Compress Buffer Size: " << out_compress.size() << std::endl;  std::cout << "========= DecompressString ===========" << std::endl;  std::string out_decompress;  assert(DecompressString(out_compress.c_str(),out_compress.size(),out_decompress) == Z_OK);  std::cout << "Decompress Buffer Size: " << out_decompress.size() << std::endl;  assert(!out_decompress.compare(buf));  return 0;}

输出:

========= CompressString ===========Source Buffer Size: 662Compress Buffer Size: 38========= DecompressString ===========Decompress Buffer Size: 662

参考

zlib/src/examples/zpipe.c

C++ Code Snippet - Compressing STL Strings with zlib

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表