简单的Zlib C++字符串压缩和解压缩

10

我需要在C++中对std::string进行简单的压缩和解压缩。我查看了这个网站,但是代码是针对字符数组的。我想要实现的是以下两个函数:

std::string original = "This is to be compressed!!!!";
std::string compressed = string_compress(original);
std::cout << compressed << std::endl;
std::string decompressed = string_decompress(compressed);
std::cout << decompressed << std::endl;

我曾经尝试使用boost压缩,方法如下:

std::string CompressData(const std::string &data)
{
    std::stringstream compressed;
    std::stringstream decompressed;
    decompressed << data;
    boost::iostreams::filtering_streambuf<boost::iostreams::input> out;
    out.push(boost::iostreams::zlib_compressor());
    out.push(decompressed);
    boost::iostreams::copy(out, compressed);
    return compressed.str();
}

std::string DecompressData(const std::string &data)
{
    std::stringstream compressed;
    std::stringstream decompressed;
    compressed << data;
    boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
    in.push(boost::iostreams::zlib_decompressor());
    in.push(compressed);
    boost::iostreams::copy(in, decompressed);
    return decompressed.str();
}

但是代码有时会在字符串中产生空字符,即 \u0000。如果压缩数据包含这些空字符,我该如何处理?返回类型string正确吗?我如何使用zlib实现函数string_compressstring_decompress


4
压缩数据只是二进制数据,它不是可读的字符串(从人类角度来看)。所以在压缩字符串中看到“奇怪”的二进制数据并不令人惊讶,毕竟那就是它本来的样子。 - Cornstalks
为什么你在意压缩字符串中是否有空字符? - Galik
由于压缩后的消息以Json字符串的形式发送到服务器,但是一旦服务器看到空字符,就无法接收完整的消息。 - Mahadeva
3
你需要对它进行编码,可以使用base64或者其他方式。这是在JSON中处理二进制数据的常用方法。 - Cornstalks
谢谢,我会试一下。 - Mahadeva
std::string 对于嵌入的 NUL 字符没有任何问题 - 你为什么会这样想呢? - sehe
2个回答

9
您可以按照@LawfulEvil的建议操作。以下是可行的代码片段 :)
std::string original = "This is to be compressed!!!!";
std::string compressed_encoded = string_compress_encode(original);
std::cout << compressed_encoded << std::endl;
std::string decompressed_decoded = string_decompress_decode(compressed_encoded);
std::cout << decompressed_decoded << std::endl;

使用这个作为base64编码/解码库。
#include <sstream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <cpp-base64/base64.h>

std::string string_compress_encode(const std::string &data)
{
    std::stringstream compressed;
    std::stringstream original;
    original << data;
    boost::iostreams::filtering_streambuf<boost::iostreams::input> out;
    out.push(boost::iostreams::zlib_compressor());
    out.push(original);
    boost::iostreams::copy(out, compressed);

    /**need to encode here **/
    std::string compressed_encoded = base64_encode(reinterpret_cast<const unsigned char*>(compressed.c_str()), compressed.length());

    return compressed_encoded;
}

std::string string_decompress_decode(const std::string &data)
{
    std::stringstream compressed_encoded;
    std::stringstream decompressed;
    compressed_encoded << data;

    /** first decode  then decompress **/
    std::string compressed = base64_decode(compressed_encoded);

    boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
    in.push(boost::iostreams::zlib_decompressor());
    in.push(compressed);
    boost::iostreams::copy(in, decompressed);
    return decompressed.str();
}

1
谢谢Zangetsu。我会尝试这段代码并告知是否有效。 - Mahadeva
3
为了完整起见,你应该列出代码的包含部分。 - Kahless
2
你的代码甚至无法编译,std::stringstream 没有 c_str()length() 方法,但是它有一个 str() 方法可以获取一个 std::string - BullyWiiPlaza
1
我遇到了一个错误 note: in instantiation of function template specialization 'boost::iostreams::detail::chain_client<boost::iostreams::chain<boost::iostreams::input, char, std::__1::char_traits<char>, std::__1::allocator<char> > >::push<std::__1::basic_string<char> >' requested here in.push(compressed); - Pablo Reinoso

2
压缩使用每个字节可用的所有值,因此在尝试以ASCII格式查看时,它将显示为“垃圾”或“奇怪”的字符。这是预期的。您需要对数据进行编码以进行传输/ JSON打包以避免空值。我建议使用base64。执行此操作的代码可在下面的链接中找到(我没有编写,因此不会复制)。
  1. http://www.adp-gmbh.ch/cpp/common/base64.html
  2. Binary data JSONCPP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接