5

How would I decompress a bzip2-compressed byte array using boost? I found an example here, but the input is a file hence the use of ifstream. The documentation isn't very clear for me :(.

Edit: I'll accept alternatives to boost.

someguy
  • 7,144
  • 12
  • 43
  • 57

1 Answers1

7

Here's my code using DEFLATE compression in the boost.iostreams library; I'm sure you can hook in the corresponding BZip2 compressor instead:

#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/filter/bzip2.hpp>   // <--- this one for you
#include <boost/iostreams/write.hpp>

  // Output

  std::ofstream datfile(filename, std::ios::binary);
  boost::iostreams::filtering_ostreambuf zdat;
  zdat.push(boost::iostreams::zlib_compressor());  // your compressor here
  zdat.push(datfile);

  boost::iostreams::write(zdat, BUFFER, BUFFER_SIZE);

  // Input

  std::ifstream datfile(filename, std::ios::binary);
  boost::iostreams::filtering_istreambuf zdat;
  zdat.push(boost::iostreams::zlib_decompressor());
  zdat.push(datfile);

  boost::iostreams::read(zdat, BUFFER, BUFFER_SIZE);

The bzip2 compressor is called bzip2_(de)compressor().

If you want a byte buffer rather than a file, use a string stream:

char mydata[N];
std::string mydatastr(mydata, N);
std::istringstream iss(mydatastr, std::ios::binary);
std::ostringstream oss(mydatastr, std::ios::binary);
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    I want to decompress from a byte array, not a file, which the example I linked to does anyway. Edit: By the way, for the output you put zlib_decompressor(), and you passed `zidx` to the read function in the input when it should be `zdat`. – someguy Aug 17 '11 at 20:53
  • Sorry, that was a typo. For a byte array, just use a string stream instead of a file stream constructed from a string constructed from your byte array. I'll add that. – Kerrek SB Aug 17 '11 at 21:00
  • If I used a string, wouldn't the bytes be copied? I'd like something more efficient. If this can't be done using boost, I'll edit the question and accept alternatives. – someguy Aug 17 '11 at 21:02
  • If you want to read from an existing buffer in place, perhaps the boost bytebuffers can provide an inplace wrapper around the existing array; or make a stringstream and set its internal stream buffer to your existing memory (I'm not entirely sure about the details for this). – Kerrek SB Aug 17 '11 at 21:05
  • Noting, of course, that one needs to pass `std::ios::binary` to the `stringstream` constructors as well – ildjarn Aug 17 '11 at 21:19
  • @ildjarn: Awesome, I didn't know that. I'll add that! – Kerrek SB Aug 17 '11 at 21:25
  • `rdbuf()->pubsetbuf()` doesn't work for `std::istringstream` because `basic_streambuf::setbuf(_Elem *, streamsize)` do nothing – Mikhail Pilin Nov 08 '16 at 09:21
  • @ildjarn: Could you comment on Mikhail's comment? – Kerrek SB Nov 09 '16 at 15:14
  • @KerrekSB : Right, it turns out all that is implementation-defined, and the way I expected it to work just happened to work on MSVC at the time. My confusion concerning it was cleared up some time ago as a result of [this](http://stackoverflow.com/a/13059195/636019) answer by Dietmar Kühl. I then went and corrected all of my related answers ([ex.](http://stackoverflow.com/a/10839810/636019)), but I didn't think to correct comments on other answers... ;-] – ildjarn Nov 10 '16 at 01:21
  • @ildjarn: OK, thanks! I'll remove the last part of this answer then. – Kerrek SB Nov 10 '16 at 14:20
  • @MikhailPilin: I removed the ill-fated suggestion. Thanks for bringing it up! – Kerrek SB Nov 10 '16 at 15:17