简体   繁体   English

如何使用Boost iostream进行流解压缩

[英]How to streaming decompress using boost iostreams

I'm using boost iostreams (1.64.0) in order to decompress zlib data. 我正在使用boost iostreams(1.64.0)来解压缩zlib数据。 I want to do streaming decompression. 我想进行流式减压。 That means the compressed data are unpredictable size. 这意味着压缩数据的大小无法预测。 I wrote the following code example. 我编写了以下代码示例。

#include <sstream>
#include <string>
#include <iostream>

#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/zlib.hpp>

int main() {
    // Compress
    std::stringstream sender;
    boost::iostreams::filtering_streambuf<boost::iostreams::input> out;
    out.push(boost::iostreams::zlib_compressor());
    out.push(sender);
    sender << "Hello World";
    std::stringstream compressed;
    boost::iostreams::copy(out, compressed);

    // Decompress
    boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
    in.push(boost::iostreams::zlib_decompressor());
    in.push(compressed);
    std::istream is(&in);
    std::size_t const buf_size = 256;
    char buf[buf_size] = { '\0' };
#if 0
    is.getline(buf, buf_size); // works fine
#else
    std::size_t read_size = is.readsome(buf, buf_size);
    std::cout << "read_size:" << read_size << std::endl;
#endif
    // http://www.cplusplus.com/reference/ios/ios/rdstate/
    std::cout << "rdstate:" << is.rdstate() << std::endl;
    std::cout << buf << std::endl;

}

I use readsome() because the size of data is unpredictable. 我使用readsome()因为数据的大小是不可预测的。 I got the following output: 我得到以下输出:

read_size:0
rdstate:0

It was unexpected for me. 这对我来说是出乎意料的。

If I use getline() instead of readsome() , I got the following output: 如果我使用getline()而不是readsome()readsome()得到以下输出:

rdstate:2
Hello World

It was expected output. 这是预期的输出。

I think that when I use readsome() , the out put should be the same. 我认为当我使用readsome() ,输出应该相同。 I can't use getline() my in actual code because the original data is binary format. 我不能在实际代码中使用getline() ,因为原始数据是二进制格式。

Is there any way to use readsome() with filtering_streambuf or any good way to streaming decompress unpredictable length binary data? 有什么方法可以将readsome()filtering_streambuf一起使用,或者有什么好的方法以流方式解压缩不可预测长度的二进制数据?

Thanks to sehe's comment , the problem is solved. 感谢sehe的评论 ,问题得以解决。

I wrote the response for the comment but it is difficult to read because codes are not well formatted. 我为评论写了响应 ,但是由于代码格式不正确,很难阅读。 So I answer by myself. 所以我自己回答。 I hope it will help for other people who have similar problem. 希望对其他有类似问题的人有所帮助。

I replaced 我更换了

std::size_t read_size = is.readsome(buf, buf_size);

with

is.read(buf, buf_size);
std::size_t read_size = is.gcount();

, then problem is solved. ,那么问题就解决了。

I had misunderstood that std::istream::read blocks until reading buf_size length data. 我误解了std::istream::read块,直到读取buf_size长度数据。 It is not true. 这不是真的。 Even if the actual read size is less than buf_size, the function returns. 即使实际读取的大小小于buf_size,该函数也会返回。 See http://www.cplusplus.com/reference/istream/istream/read/ . 参见http://www.cplusplus.com/reference/istream/istream/read/ In order to get read_size , I call std::istream::gcount() . 为了获得read_size ,我调用了std::istream::gcount() See http://www.cplusplus.com/reference/istream/istream/gcount/ . 参见http://www.cplusplus.com/reference/istream/istream/gcount/

NOTE: I had gotten confused with boost::asio::read and boost::asio::ip::tcp::socket::read_some . 注意:我对boost::asio::readboost::asio::ip::tcp::socket::read_some But their behavior are different from std::istream 's one. 但是它们的行为不同于std::istream的行为。

Here is the complete code of the fixed version: 这是固定版本的完整代码:

#include <sstream>
#include <string>
#include <iostream>

#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/zlib.hpp>

int main() {
    // Compress
    std::stringstream sender;
    boost::iostreams::filtering_streambuf<boost::iostreams::input> out;
    out.push(boost::iostreams::zlib_compressor());
    out.push(sender);
    sender << "Hello World";
    std::stringstream compressed;
    boost::iostreams::copy(out, compressed);

    // Decompress
    boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
    in.push(boost::iostreams::zlib_decompressor());
    in.push(compressed);
    std::istream is(&in);
    std::size_t const buf_size = 256;
    char buf[buf_size] = { '\0' };
    is.read(buf, buf_size);
    std::size_t read_size = is.gcount();
    std::cout << "read_size:" << read_size << std::endl;
    // http://www.cplusplus.com/reference/ios/ios/rdstate/
    std::cout << "rdstate:" << is.rdstate() << std::endl;
    std::cout << buf << std::endl;

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM