将文件从 Boost filtering_streambuf 解压缩到 std::vector<char>?

Decompress file from Boost filtering_streambuf to std::vector<char>?

本文关键字:vector gt lt std char Boost 文件 filtering 解压缩 streambuf      更新时间:2023-10-16

我正在尝试解压缩一个使用 DEFLATE 算法压缩的文件并将其填充到vector<unsigned char>中。从我到目前为止所做的研究来看,我似乎可以使用boost::iostreams::filtering_streambuf,然后使用boost::iostreams::copy()将其放入boost::interprocess::basic_vectorstream<std::vector<unsigned char>>,然后将底层向量从向量流中拉出。但是,我遇到了大量的编译器错误,从这个开始:

/usr/include/boost/iostreams/copy.hpp: In function ‘std::streamsize boost::iostreams::detail::copy_impl(Source, Sink, std::streamsize) [with Source = boost::reference_wrapper<boost::iostreams::filtering_streambuf<boost::iostreams::input> >, Sink = boost::reference_wrapper<boost::interprocess::basic_vectorstream<std::vector<unsigned char> > >, std::streamsize = long int]’:
/usr/include/boost/iostreams/copy.hpp:245:79:   instantiated from ‘std::streamsize boost::iostreams::copy(Source&, Sink&, std::streamsize, typename boost::enable_if<boost::iostreams::is_std_io<Source> >::type*, typename boost::enable_if<boost::iostreams::is_std_io<Sink> >::type*) [with Source = boost::iostreams::filtering_streambuf<boost::iostreams::input>, Sink = boost::interprocess::basic_vectorstream<std::vector<unsigned char> >, std::streamsize = long int, typename boost::enable_if<boost::iostreams::is_std_io<Source> >::type = void, typename boost::enable_if<boost::iostreams::is_std_io<Sink> >::type = void]’
ValueFileReader.cpp:92:41:   instantiated from here
/usr/include/boost/iostreams/copy.hpp:178:5: error: static assertion failed: "(is_same<src_char, snk_char>::value)"

我正在使用的代码如下(为了简洁起见,缩短并在此处执行"使用命名空间"):

using namespace boost::iostreams;
using namespace boost::interprocess;
filtering_streambuf<input> in;
std::ifstream file(filename, std::ifstream::in);
in.push(zlib_decompressor());
in.push(file);
basic_vectorstream<std::vector<unsigned char>> vectorStream;
copy(in, vectorStream);
std::vector<unsigned char> chars(vectorStream.vector());

我已经看到了这个线程,但我不确定是否将所有内容复制到向量中,然后从向量解压缩将是最有效的方法。

有没有更好的方法可以解决这个问题,或者我的想法是正确的,但代码中有一些错误?

问题是您的ifstreamfiltering_streambuf使用 char 作为其基础字符类型,但您的basic_vectorstream使用 unsigned char 作为其值类型。Boost 代码有一个静态断言,要求这些类型相同,以便在使用两种不可转换的不同类型时不会出现编译器错误。

幸运的是,这里的修复很容易 - 更改:

basic_vectorstream<std::vector<unsigned char>> vectorStream;
copy(in, vectorStream);
std::vector<unsigned char> chars(vectorStream.vector());

自:

basic_vectorstream<std::vector<char>> vectorStream;
copy(in, vectorStream);
std::vector<unsigned char> chars(
    vectorStream.vector().begin(),
    vectorStream.vector().end()
);

这是安全的,因为charunsigned char由C++标准保证具有相同的对象表示(§3.9.1/1)。


与您的直接问题无关,但您还需要将std::ios::binary传递给 file 的构造函数,否则您将由于行尾转换而导致数据损坏。