10

I need a simple compression and decompression of a std::string in C++. I looked at this site and the code is for Character array. What I want to implement are the two functions:

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;

I had tried the boost compression as:

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();
}

but the code sometimes gives Null characters in string ie \u0000. How do I handle if the compressed data contains these null characters. Is the return type string correct? How can I implement function string_compress and string_decompress using zlib?

Mahadeva
  • 1,584
  • 4
  • 23
  • 56
  • 4
    Compressed data is just binary data. It's not a sensible, readable string (in the human sense). So it's not surprising you're seeing "weird" binary data in the compressed string. That is, after all, exactly what it is. – Cornstalks Dec 17 '14 at 15:58
  • Why do you care if there are null characters in the compressed string? – Galik Dec 17 '14 at 15:59
  • Because the compressed message is sent to Server as Json string. But the server cannot receive the full message once it sees the null character. – Mahadeva Dec 17 '14 at 16:00
  • 3
    @SarvagyaPant: Then you need to encode it, either with base64 or [something else](http://stackoverflow.com/questions/1443158/binary-data-in-json-string-something-better-than-base64). That's what everyone does with binary data in JSON. – Cornstalks Dec 17 '14 at 16:01
  • `std::string` has no problem whatsoever with embedded NUL characters - what made you think so? – sehe Dec 17 '14 at 20:16

2 Answers2

8

You can do as @LawfulEvil suggested. Here is the code snippet that works :)

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;

Using this as the base64 encode/decode library.

#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();
}
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
Zangetsu
  • 1,900
  • 17
  • 25
  • 1
    Thanks Zangetsu. I will be trying this code and inform if this works. – Mahadeva Dec 19 '14 at 04:45
  • 3
    You should really list the include section of your code for completeness. – Kahless Jan 03 '17 at 03:16
  • 2
    Your code does not even compile, `std::stringstream` does not have a `c_str()` or `length()` method, it has a `str()` method though to get a `std::string`. – BullyWiiPlaza Apr 01 '20 at 16:46
  • 1
    I got an error `note: in instantiation of function template specialization 'boost::iostreams::detail::chain_client, std::__1::allocator > >::push >' requested here in.push(compressed);` – Pablo Reinoso Oct 20 '20 at 15:54
2

Compression makes use of all the values available for each byte, so it will appear as 'garbage' or 'weird' characters when attempting to view as ascii. Its expected. You'll need to encode the data for transmission / json packing to avoid nulls. I suggest base 64. Code to do that is available at the link below(which I didn't author so I won't copy here).

  1. http://www.adp-gmbh.ch/cpp/common/base64.html
  2. Binary data JSONCPP
Community
  • 1
  • 1
LawfulEvil
  • 2,267
  • 24
  • 46