boost gzip распаковывает байтовый массив - PullRequest
10 голосов
/ 03 февраля 2012

Я реализовал распаковку файлов gzip / zlib, как показано в их примерах на сайте наддува.

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

это отлично работает. Я также читаю данные из сокета, который я получаю из службы JSON, основанной на отдыхе, которая также сжимается. Я подумал, что напишу реализацию на основе памяти, насколько это может быть сложно. Ну, я понял, что не понимаю потоки и потоковые буферы так, как должен. Я обвиняю последние несколько лет в Java;) .. Так что я пошел по этому пути.

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

Но я в растерянности относительно того, какой тип потока я могу использовать, чтобы в основном получить распакованное char* представление распакованного потока. Это должно быть легко, и, вероятно, так и есть, но последние пару часов я тратил впустую на неудачные попытки.

1 Ответ

6 голосов
/ 19 февраля 2012

Очевидно, вы столкнулись с фильтрацией потоков и потоковых буферов .Вы можете использовать тот же метод в обратном порядке, чтобы получить данные в строку.

У меня нет собственных удобных примеров, поэтому посчитайте, что это несколько псевдокод, но это должно быть то, что вы ищете:

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

Таким образом, вы можете использовать задний вкладыш, предоставленный Boost.

По сути, вышеприведенный код определяет выходной поток, в который вы можете писать.Он настроен таким образом, чтобы весь записанный в него контент сначала распаковывался gzip, а , а затем добавлялся к back_inserter, который, как и back_inserters, вставлялся в конец decompressedbuffer.

Также, как вы можете видеть, буферы заключены в std::vector.Дайте мне знать, если это работает для вас.

...