Boost 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&一世;
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 if(i == eof){
std :: cout< ; 到达eof之后< j<< bytes\\\
;
return -1;
}
char next = * i ++;
std :: cout<< 阅读<<下一个< \\\
;
* 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;
}
要提供此输出:
阅读x
阅读
阅读s
阅读
阅读
阅读
阅读B
Reading
Reading B
在9个字节后达到eof
在抛出boost :: exception_detail :: clone_impl< boost :: exception_detail :: error_info_injector< boost :: iostreams :: zlib_error> >'
what():zlib错误
中止(转储核心)
EDIT 为了回应澄清的问题(在下面的评论中),以下是我对原始示例,我的盒子上的 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&它;
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);
}
旧答案:
我认为您只能使用任何流stringstream:
std :: istringstream iss(hello world\\\
);
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\\\
$(echo hello world | zlib-flate -compress)
,我很懒得保持这种方式)。
完整示例 Live on Coliru
或 Boost Iostreams接受流缓冲区,因此您可以等效
def.push(* iss.rdbuf());
I am trying to use a
zlib_decompressor
to decompress data through anistreambuf_iterator
. I couldn't find an in built way to use an input iterator as input to a stream (please point out a way if one exists already) so I wrote this source: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; } };
And used it like this:
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; }
To give this output:
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)
I am not sure why this is producing an error because loading from a file works fine.
解决方案EDIT In response to the clarified question (in the comments below), here's a trivial adaptation I did of your original sample, that JustWorks™ on my box:
#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); }
See it Live On Coliru
Old answer:
I think you can use just any stream, like stringstream:
std::istringstream iss("hello world\n"); filtering_streambuf<input> def; def.push(zlib_compressor()); def.push(iss); boost::iostreams::copy(def, std::cout);
or to decompress:
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);
This works like a charm here. (Sorry for the octal escapes: it's what bash gave me
printf "%q\n" "$(echo hello world | zlib-flate -compress)"
and I'm lazy enough to keep it that way).
See full example Live on Coliru
Alternatively Boost Iostreams accepts a streambuffer, so you can equivalently
def.push(*iss.rdbuf());
这篇关于Boost Iostreams zlib_error与自定义源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!