簡體   English   中英

使用自定義源提升Iostreams zlib_error

[英]Boost Iostreams zlib_error with Custom Source

我試圖使用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 << " bytes\n";
                    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', '\002', '\0', '\036', 'r', '\004', '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);
}

看到Live On Coliru


老答案

我想你可以使用任何流,比如stringstream:

std::istringstream iss("hello world\n");

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', '\002', '\0', '\036', 'r', '\004', '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 "%q\n" "$(echo hello world | zlib-flate -compress)"

而且我很懶,保持這種方式)。

查看Live on Coliru的完整示例


或者, Boost Iostreams接受一個streambuffer,所以你可以等效

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM