Boost 1.59 не распаковывает все потоки bzip2

Я пытался распаковать некоторые файлы .bz2 на лету и, если можно так выразиться, построчно, так как файлы, с которыми я имею дело, являются массивными без сжатия (область без сжатия 100 ГБ), поэтому я хотел добавить решение, которое экономит дисковое пространство.

У меня нет проблем с распаковкой файлов, сжатых с помощью vanilla bzip2, но файлы, сжатые с помощью pbzip2, распаковывают только первый найденный поток bz2. Этот багтрекер относится к проблеме: https://svn.boost.org/trac/boost/ticket/3853 но я поверил, что это было исправлено в предыдущей версии 1.41. Я проверил файл bzip2.hpp, и он содержит «фиксированную» версию, а также проверил, что версия Boost, используемая в программе, — 1.59.

Код здесь:

cout<<"Warning bzip2 support is a little buggy!"<<endl;

//Open the file here
trans_file.open(files[i].c_str(), std::ios_base::in |  std::ios_base::binary);

//Set up boost bzip2 compression
boost::iostreams::filtering_istream in;
in.push(boost::iostreams::bzip2_decompressor());
in.push(trans_file);
std::string str;

//Begin reading
while(std::getline(in, str))
{
std::stringstream stream(str);
stream>>id_f>>id_i>>aif;
/* Do stuff with values here*/
}

Любые предложения будут великолепны. Спасибо!

3

Решение

Вы правы.

Кажется, что changeset # 63057 только исправляет часть проблемы.

Тем не менее, соответствующий юнит-тест работает. Но он использует copy алгоритм (также на composite<> вместо filtering_istream, если это актуально).

Я бы открыл это как дефект или регресс. Разумеется, включите файл, в котором обнаружена проблема. Для меня это воспроизводится с использованием только /etc/dictionaries-common/words сжатый с pbzip2 (параметры по умолчанию).

у меня есть test.bz2 Вот: http://7f0d2fd2-af79-415c-ab60-033d3b494dc9.s3.amazonaws.com/test.bz2

Вот моя тестовая программа:

#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/stream.hpp>
#include <fstream>
#include <iostream>

namespace io = boost::iostreams;

void multiple_member_test(); // from the unit tests in changeset #63057

int main() {
//multiple_member_test();
//return 0;

std::ifstream trans_file("test.bz2", std::ios::binary);

//Set up boost bzip2 compression
io::filtering_istream in;
in.push(io::bzip2_decompressor());
in.push(trans_file);

//Begin reading
std::string str;
while(std::getline(in, str))
{
std::cout << str << "\n";
}
}

#include <boost/iostreams/compose.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/device/back_inserter.hpp>
#include <cassert>
#include <sstream>

void multiple_member_test()  // from the unit tests in changeset #63057
{
std::string      data(20ul << 20, '*');
std::vector<char>  temp, dest;

// Write compressed data to temp, twice in succession
io::filtering_ostream out;
out.push(io::bzip2_compressor());
out.push(io::back_inserter(temp));
io::copy(boost::make_iterator_range(data), out);
out.push(io::back_inserter(temp));
io::copy(boost::make_iterator_range(data), out);

// Read compressed data from temp into dest
io::filtering_istream in;
in.push(io::bzip2_decompressor());
in.push(io::array_source(&temp[0], temp.size()));
io::copy(in, io::back_inserter(dest));

// Check that dest consists of two copies of data
assert(data.size() * 2 == dest.size());
assert(std::equal(data.begin(), data.end(), dest.begin()));
assert(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2));

dest.clear();
io::copy(
io::array_source(&temp[0], temp.size()),
io::compose(io::bzip2_decompressor(), io::back_inserter(dest)));

// Check that dest consists of two copies of data
assert(data.size() * 2 == dest.size());
assert(std::equal(data.begin(), data.end(), dest.begin()));
assert(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2));
}
3

Другие решения

Других решений пока нет …