使用自定义源提升 iostream zlib_error

Boost Iostreams zlib_error with Custom Source

本文关键字:iostream zlib error 自定义      更新时间:2023-10-16

我正在尝试使用zlib_decompressor通过istreambuf_iterator解压缩数据。我找不到使用输入迭代器作为流输入的内置方式(如果已经存在,请指出一种方法),所以我写了这个源代码:

template <class cha_type, class iterator_type>
class IteratorSource {
    public:
        typedef cha_type char_type;
        typedef boost::iostreams::source_tag category;
        iterator_type& i;
        iterator_type eof;
        IteratorSource(iterator_type& it, iterator_type end) : i(it), eof(end) {
        }
        std::streamsize read(char* s, std::streamsize n) {
            for(int j = 0; j < n; j++) {
                if(i == eof) {
                    std::cout << "Reached eof after " << j << " bytesn";
                    return -1;
                }
                char next = *i++;
                std::cout << "Reading " << next << "n";
                *s++ = next;
            }
            return n;
        }
};

并像这样使用它:

int main() {       
    std::vector<char> data_back = {'x78', 'x9c', 'x73', 'x04', 'x00', 'x00', 'x42', 'x00', 'x42'};
    auto start = data_back.begin();
    IteratorSource<char, decltype(data_back)::iterator> data(start, data_back.end());
    boost::iostreams::filtering_istreambuf def;
    def.push(boost::iostreams::zlib_decompressor());
    def.push(data);
    boost::iostreams::copy(def, std::cout);
    return 0;
}

要提供此输出,请执行以下操作:

Reading x
Reading �
Reading s
Reading 
Reading 
Reading 
Reading B
Reading 
Reading B
Reached eof after 9 bytes
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::iostreams::zlib_error> >'
  what():  zlib error
Aborted (core dumped)

我不确定为什么会产生错误,因为从文件加载工作正常。

编辑 为了回答澄清的问题(在下面的评论中),这是我对您的原始样本所做的一个微不足道的改编,即我的盒子上的 JustWorks™

#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <iostream>
#include <sstream>
template <class cha_type, class iterator_type>
struct my_source {
    typedef cha_type char_type;
    typedef boost::iostreams::source_tag category;
    iterator_type& it;
    iterator_type end;
    my_source(iterator_type& it, iterator_type end = {}) : it(it), end(end) 
    { }
    std::streamsize read(char* s, std::streamsize n) {
        std::streamsize result = 0;
        while ((it!=end) && n--) {
            ++result;
            *s++ = *it++;
        }
        return result;
    }
};
int main() {       
    std::string const rawdata {'x', '234', '313', 'H', '315', '311', '311', 'W', '(', '317', '/', '312', 'I', '341', '02', '', '36', 'r', '04', 'g' };
    std::istringstream iss(rawdata, std::ios::binary);
    auto start = std::istreambuf_iterator<char>(iss);
    my_source<char, decltype(start)> data(start);
    boost::iostreams::filtering_istreambuf def;
    def.push(boost::iostreams::zlib_decompressor());
    def.push(data);
    boost::iostreams::copy(def, std::cout);
}

科里鲁现场观看


旧答案

我认为您可以使用任何流,例如字符串流:

std::istringstream iss("hello worldn");
filtering_streambuf<input> def;
def.push(zlib_compressor());
def.push(iss);
boost::iostreams::copy(def, std::cout);

或解压:

std::string const rawdata {'x', '234', '313', 'H', '315', '311', '311', 'W', '(', '317', '/', '312', 'I', '341', '02', '', '36', 'r', '04', 'g' };
std::istringstream iss(rawdata, std::ios::binary);
filtering_streambuf<input> def;
def.push(zlib_decompressor());
def.push(iss);
boost::iostreams::copy(def, std::cout);

这在这里就像一个魅力。(对不起,八进制逃脱:这就是bash给我的

printf "%qn" "$(echo hello world | zlib-flate -compress)"

而且我懒得保持这种状态)。

查看完整示例 在科里鲁直播


或者,Boost Iostreams 接受流缓冲区,因此您可以等效地

def.push(*iss.rdbuf());