Question

I implemented the gzip/zlib decompression of files as shown in their examples on the boost site.

void CompressionUtils::Inflate(std::ifstream& inputFile,
                               std::ofstream& outputFile)
{
   boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
   in.push(boost::iostreams::gzip_decompressor());
   in.push(inputFile);
   boost::iostreams::copy(in, outputFile);
}

this works fine. I am also reading data from a socket that I am getting from a rest based JSON service that is compressed as well. I figured I would write a memory based implementation, how hard could that be. Well, I figured out I do not understand the streams and stream buffers as I should. I blame the last few years in Java ;) .. So I started down this path.

void CompressionUtils::Inflate(char* compressed, 
                               int size,
                               char* decompressed)
{

   boost::iostreams::stream<boost::iostreams::array_source> source(compressed,size);
   //std::stringstream str;

   boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
   in.push(boost::iostreams::gzip_decompressor());
   in.push(source);
   //boost::iostreams::copy(in, str);   
}

But I am at a loss as to what kind of stream I can use to basically get the decompressed char* representation of the decompressed stream. This should be easy, and probably is, but I have been wasting the last couple hours coming up with unsuccessful attempts.

Was it helpful?

Solution

Obviously, you've come across filtering streams and stream buffers. You can use the same method in reverse to get data into a string.

I don't have my own examples handy, so consider this to be somewhat pseudo-code but this should be what you're looking for:

namespace io = boost::iostreams; //<-- good practice
typedef std::vector<char> buffer_t;

void CompressionUtils::Inflate(const buffer_t &compressed,
                               buffer_t &decompressed)
{
    io::filtering_ostream os;

    os.push(io::gzip_decompressor());
    os.push(io::back_inserter(decompressed));

    io::write(os, &compressed[0], compressed.size());
}

So you can use the back inserter provided by Boost.

Basically, what the above code does is define an output stream which you can write to. It is set up so that all content written to it will first be decompressed by gzip, and then appended to the back_inserter which will, as back_inserters do, insert into the back of the decompressed buffer.

Also, as you can see, the buffers are wrapped in std::vector. Let me know if this works for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top