场景

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

[Zlib]_[初级]_[使用zlib库压缩和解压STL string]的更多相关文章

  1. C#文件或文件夹压缩和解压方法(通过ICSharpCode.SharpZipLib.dll)

    我在网上收集一下文件的压缩和解压的方法,是通过ICSharpCode.SharpZipLib.dll 来实现的 一.介绍的目录 第一步:下载压缩和解压的 ICSharpCode.SharpZipLib ...

  2. 黄聪:.NET中zip的压缩和解压——SharpCompress

    使用Packaging无法实现通用的zip(使用其他工具压缩)的解压,只支持通过Packaging压缩包zip的解压,而SharpZipLib是基于“GPL”开源方式,风险比较大.在codeplex找 ...

  3. [Swift通天遁地]七、数据与安全-(9)文件的压缩和解压

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  4. C#压缩和解压文件

    这里用两种方法实现C#压缩和解压文件 1.使用System.IO.Compression名称空间下的相关类(需引用 System.IO.Compression.FileSystem和System.IO ...

  5. 【C#公共帮助类】WinRarHelper帮助类,实现文件或文件夹压缩和解压,实战干货

    关于本文档的说明 本文档使用WinRAR方式来进行简单的压缩和解压动作,纯干货,实际项目这种压缩方式用的少一点,一般我会使用第三方的压缩dll来实现,就如同我上一个压缩类博客,压缩的是zip文件htt ...

  6. java 文件压缩和解压(ZipInputStream, ZipOutputStream)

    最近在看java se 的IO 部分 , 看到 java 的文件的压缩和解压比较有意思,主要用到了两个IO流-ZipInputStream, ZipOutputStream,不仅可以对文件进行压缩,还 ...

  7. C#实现通过Gzip来对数据进行压缩和解压

    C#实现通过Gzip来对数据进行压缩和解压 internal static byte[] Compress(byte[] data) { using (var compressedStream = n ...

  8. linux常用命令:4文件压缩和解压命令

    文件压缩和解压命令 压缩命令:gzip.tar[-czf].zip.bzip2 解压缩命令:gunzip.tar[-xzf].unzip.bunzip2 1. 命令名称:gzip 命令英文原意:GNU ...

  9. .net文件压缩和解压及中文文件夹名称乱码问题

    /**************************注释区域内为引用http://www.cnblogs.com/zhaozhan/archive/2012/05/28/2520701.html的博 ...

随机推荐

  1. springboot 1.3.5升级1.5.9后 默认使用tomcat 8.5版本 get请求报400 异常信息为 The valid characters are defined in RFC 7230 and RFC 3986

    1.springboot 1.3.5升级1.5.9后 默认使用tomcat 8.5版本而之前用的是tomcat7    get请求报400 异常信息为 The valid characters are ...

  2. Problem4-Project Euler

    Largest palindrome product   A palindromic number reads the same both ways. The largest palindrome m ...

  3. ubuntu下配置时间同步NTP

    1参考文献: 1.鸟哥的Linux私房菜:第十五章.时间服务器: NTP 服务器(强烈建议看完) 2.http://www.crsay.com/wiki/wiki.php/server/centos/ ...

  4. Safari中的Date

    在js中处理Date时,发现Safari和其他浏览器的支持方式不一致 1.例如:2017-01-01 12:00:00 在其他浏览器中,使用这个格式的字符串进行new Date操作没有问题,但是在Sa ...

  5. 详解Oracle DELETE和TRUNCATE 的区别

    原文地址:http://www.cnblogs.com/simplefrog/archive/2012/07/30/2615169.html 语法delete from aa truncate tab ...

  6. 【待补充】[Linux] nc

    [nc 是做什么的] [nc怎么用] 查看帮助 nc -help # 查看帮助 nc -help # 监听端口 -l, --listen Bind and listen for incoming co ...

  7. Coursera-AndrewNg(吴恩达)机器学习笔记——第三周编程作业(逻辑回归)

    一. 逻辑回归 1.背景:使用逻辑回归预测学生是否会被大学录取. 2.首先对数据进行可视化,代码如下: pos = find(y==); %找到通过学生的序号向量 neg = find(y==); % ...

  8. 设置联想键盘恢复F1~F12默认按键的操作办法

    背景 默认都是笔记本键盘才有Fn组合功能键,台式机很少有.今天领到的是联想键盘,给我的台式机使用后F12很麻烦,必须Fn+F12才可以. 需求 恢复默认的F1~F12功能 方案 只需要下载驱动安装: ...

  9. Docker 使用入门,创建一个Nginx服务器

    运行环境: MAC Docker 版本: Docker version 17.12.0-ce, build c97c6d6 一.启动Nginx 服务器 启动Nginx 服务器,并进入模拟终端 dock ...

  10. 读高性能JavaScript编程 第二章 让我知道了代码为什么要这样写

    代码为什么要这样写? function initUI(){ var doc = document, bd = doc.body, links = doc.getElementsByTagName_r( ...