Boost 1.59无法解压全部的bzip2流。

4

我一直在试图对一些.bz2文件进行即时逐行解压缩,因为我处理的文件非常大(未压缩约100GB),因此我想添加一个节省磁盘空间的解决方案。

使用普通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*/
}

任何建议都会很棒。谢谢!

在 https://svn.boost.org/trac/boost/ticket/9749 的评论中发布的补丁已经为我解决了这个问题。不幸的是,这个漏洞现在已经存在相当长的时间了。 - PiQuer
看起来这个问题在某个时候已经被修复了,补丁svn.boost.org/trac/boost/ticket/9749似乎已经被合并到boost/iostreams/filter/bzip2.hpp中。使用Boost 1.72,我现在可以成功解压多流文件。 - HyperBoar
1个回答

4

你是正确的。

似乎更改集#63057只解决了问题的一部分。

相应的单元测试确实有效。但它使用了copy算法(也用于composite<>而不是filtering_istream,如果这很重要)。

我会将其作为缺陷或回归进行开放。当然,要包含一个展示问题的文件。对我来说,只需使用默认选项压缩/etc/dictionaries-common/words即可复现问题。

我这里有test.bz2http://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)); 
} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接