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

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: 662
Compress Buffer Size: 38
========= DecompressString ===========
Decompress Buffer Size: 662

参考

zlib\src\examples\zpipe.c

C++ Code Snippet - Compressing STL Strings with zlib

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

(0)

相关推荐

  • C++ STL list 遍历删除出错解决方案

    C++ STL list 遍历删除崩溃 错误用法一 下面这种用法会在for的地方崩溃,分析 第一次for循环的时候 it=0,当t.erase(it)执行完成之后 it就变成了 -17891602 表明it不能再作为迭代器进行运算,自然会报错. #include <map> #include <list> using namespace std; typedef std::list<int > TESTLIST; int _tmain(int argc, _TCHAR*

  • C++ STL入门教程(2) list双向链表使用方法(附程序代码)

    一.简介 "Unlike other standard sequence containers, list and forward_list objects are specifically designed to be efficient inserting and removing elements in any position, even in the middle of the sequence." Lists将元素按顺序储存在链表中.与向量(vector)相比, 它允许快速

  • C++ STL入门教程(1) vector向量容器使用方法

    一.简介 Vectors 包含着一系列连续存储的元素,其行为和数组类似. 访问Vector中的任意元素或从末尾添加元素都可以在O(1)内完成,而查找特定值的元素所处的位置或是在Vector中插入元素则是O(N). 二.完整程序代码 /*请务必运行以下程序后对照阅读*/ #include <vector> #include <iostream> #include <algorithm> #include <stdexcept> using namespace

  • C++ STL入门教程(3) deque双向队列使用方法

    一.简介 deque(Double Ended Queues,双向队列)和向量很相似,但是它允许在容器头部快速插入和删除(就像在尾部一样). 二.完整程序代码 /*请务必运行以下程序后对照阅读*/ #include <deque> #include <iostream> #include <algorithm> #include <stdexcept> using namespace std; void print(int num) { cout <&

  • C++ STL入门教程(6) set(集合)的使用方法

    一.简介 集合(Set)是一种包含已排序对象的关联容器,不允许有重复元素. 二.完整程序代码 /*请务必运行以下程序后对照阅读*/ #include <set> #include <iostream> using namespace std; int main() { ///1. 初始化 set<int> num; set<int>::iterator iter; cout << num.max_size() << endl;///s

  • C++ STL入门教程(7) multimap、multiset的使用

    一.multimap(一对多索引) C++ multimap和map所支持的操作相同(除了multimap不支持下标运算),但是multimap允许重复的元素. 完整程序代码: /*请务必运行以下程序后对照阅读*/ ///头文件依旧是map #include <map> #include <string> #include <iostream> using namespace std; int main() { ///1. 初始化 multimap<int, st

  • C++中 STL list详解及简单实例

    C++中 STL list详解 1.List: 内部实现是一个双向链表,可以高效的进行插入删除,但不能够进行随机访问 2..示例程序: #include "stdafx.h" #include <iostream> #include <list> #include <iterator> #include <algorithm> using namespace std; const int num[5] = {1,3,2,4,5}; boo

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

    zlib库压缩和解压字符串STL string的实例详解 场景 1.一般在使用文本json传输数据, 数据量特别大时,传输的过程就特别耗时, 因为带宽或者socket的缓存是有限制的, 数据量越大, 传输时间就越长. 网站一般使用gzip来压缩成二进制. 说明 1.zlib库可以实现gzip和zip方式的压缩, 这里只介绍zip方式的二进制压缩, 压缩比还是比较可观的, 一般写客户端程序已足够. 2.修改了一下zpipe.c的实现, 其实就是把读文件改为读字符串, 写文件改为写字符串即可. 例子

  • C++数据结构之文件压缩(哈夫曼树)实例详解

    C++数据结构之文件压缩(哈夫曼树)实例详解 概要: 项目简介:利用哈夫曼编码的方式对文件进行压缩,并且对压缩文件可以解压 开发环境:windows vs2013 项目概述:         1.压缩 a.读取文件,将每个字符,该字符出现的次数和权值构成哈夫曼树 b.哈夫曼树是利用小堆构成,字符出现次数少的节点指针存在堆顶,出现次数多的在堆底 c.每次取堆顶的两个数,再将两个数相加进堆,直到堆被取完,这时哈夫曼树也建成 d.从哈夫曼树中获取哈夫曼编码,然后再根据整个字符数组来获取出现了得字符的编

  • python压包的概念及实例详解

    对于一些分解后的元素,我们也是有重新归类的需要.那么我们把解包的恢复过程,叫做压包.这里要用到zip函数的方法,对元素重新进行打包处理,在之前的学习中我们已经对zip函数有所接触.下面我们就python压包的概念.方法进行介绍,然后带来相关的实例使用. 1.概念 压包是解包的逆过程,用zip函数实现. 2.方法 (1)zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象(Python3). (2)如果各个迭代器的元素个数不一致,则返回列表长

  • C++定义和初始化string对象实例详解

    目录 正文 定义string 初始化string 全面初始化 默认初始化 拷贝初始化 直接初始化 正文 在c++当中,标准类型string来代表可变长的字符串序列,使用string需要加载string 头文件,而方法定义在命名空间std当中,所以使用的基本结构: #include <string> int main(){ using std::string; string str1 = "hello world"; return 0; } 当然也可以结合之前的输入输出部分:

  • 汇编语言功能字符串大小写转换实现实例详解

    目录 问题1:将data段中的第一个字符串转换成大写,第二个字符串转换成小写 问题2:将data段中每个单词的头一个字母改成大写字母 问题3:将data段中每个单词改为大写字母 问题4:将data段中每个单词的前4个字母改为大写字母 问题5:设计一个子程序,将一个全是字母的字符串转化成大写 问题6:设计一个子程序,将一个全是字母,以0结尾的字符串,转化成大写 复杂一点的对结构化数据的版本 问题1:将data段中的第一个字符串转换成大写,第二个字符串转换成小写 分析: 如何转换成大小写 如果利用A

  • python开发之字符串string操作方法实例详解

    本文实例讲述了python开发之字符串string操作方法.分享给大家供大家参考,具体如下: 在python中,对于字符串string的操作,我们有必要了解一下,这样在我们的以后的开发中会给我们带来很多方便 下面是我学习的笔记: #python-string #python中的字符串用单引号''和双引号""标示 strA = 'this is a string' strB = "this is a message!" #打印两个字符串 print("打印两

  • C#中string用法实例详解

    在进行C#程序设计时,用的最多的莫过于string了,但有些时候由于不仔细或者基础的不牢固等因素容易出错,今天本文就来较为详细的总结一下C#中string的用法.具体如下: 1.string是一个引用类型,平时我们比较string对象,比较的是对象的值而不是对象本身 如下面代码所示: string strA="abcde"; string strB="abc"; string strC="de"; Console.WriteLine(strA =

  • Python基础之字符串常见操作经典实例详解

    本文实例讲述了Python基础之字符串常见操作.分享给大家供大家参考,具体如下: 字符串基本操作 切片 # str[beg:end] # (下标从 0 开始)从下标为beg开始算起,切取到下标为 end-1 的元素,切取的区间为 [beg, end) str = ' python str ' print (str[3:6]) # tho # str[beg:end:step] # 取 [beg, end) 之间的元素,每隔 step 个取一个 print (str[2:7:2]) # yhn 原

  • Python字符串的全排列算法实例详解

    本文实例讲述了Python字符串的全排列算法.分享给大家供大家参考,具体如下: 题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 输入描述 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母. 注意有可能重复,因此需要判断 注意list的append方法和list的+方法的区别 append方法在list后面添加元素 +方法在list后面添加l

  • python中内置函数ord()返回字符串的ASCII数值实例详解

    目录 常用 ASCII 码表对照表: ord()函数介绍: 应用实例: 常用 ASCII 码表对照表: 注意如下几点: 0-9:48-57A-Z:65-90a-z:97-122 ord()函数介绍: ord() 函数是 chr() 函数(对于 8 位的 ASCII 字符串)的配对函数,它以一个字符串(Unicode 字符)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值. >>> ord('0') 48 >>> ord('A') 65 >>

随机推荐