2017-06-21 1 views
0

Ich verwende Boost-Iostreams (1.64.0), um Zlib-Daten zu dekomprimieren. Ich möchte Streaming Dekompression tun. Das bedeutet, dass die komprimierten Daten eine unvorhersehbare Größe haben. Ich schrieb das folgende Codebeispiel.How to Streaming Dekomprimieren mit Boost Iostreams

#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; 

} 

Ich benutze readsome(), weil die Größe der Daten nicht vorhersehbar ist. Ich habe die folgende Ausgabe:

read_size:0 
rdstate:0 

Es war für mich unerwartet.

Wenn ich getline() statt readsome(), bekam ich die folgende Ausgabe:

rdstate:2 
Hello World 

Es Ausgang erwartet wurde.

Ich denke, wenn ich readsome() benutze, sollte der Ausgang der gleiche sein. Ich kann getline() meine in tatsächlichen Code nicht verwenden, da die ursprünglichen Daten Binärformat sind.

Gibt es eine Möglichkeit, readsome() mit filtering_streambuf oder eine gute Möglichkeit zum Streaming zu verwenden dekomprimieren unvorhersehbare Länge Binärdaten?

+1

Warum nicht verwenden 'read()' statt – sehe

+1

Danke für den Kommentar. Ich habe festgestellt, dass ich "istream = read()" und "istream = readsome()" missverstanden habe und mich wie "boost asio" 'read()' und 'socket :: read_some()' verhält. I ersetzt 'std :: size_t read_size = is.readsome (buf, buf_size);' ' std :: cout << "read_size:" << read_size << std :: endl;' mit 'ist.lesen (buf, buf_size); ' ' std :: size_t read_size = ist.gcount(); ' ' std :: cout << "read_size:" << lesen_größe << std :: endl; ' dann meine Code funktioniert wie erwartet. –

Antwort

0

Dank sehe's comment ist das Problem gelöst.

Ich schrieb the response für den Kommentar, aber es ist schwer zu lesen, weil Codes nicht gut formatiert sind. Also antworte ich alleine. Ich hoffe, dass es für andere Leute helfen wird, die ähnliches Problem haben.

I

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

mit

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

ersetzt, dann wird Problem gelöst.

Ich hatte das std::istream::read Blöcke bis zum Lesen buf_size Länge Daten missverstanden. Es ist nicht wahr. Selbst wenn die tatsächliche Lesegröße kleiner als buf_size ist, kehrt die Funktion zurück. Siehe http://www.cplusplus.com/reference/istream/istream/read/. Um read_size zu erhalten, rufe ich std::istream::gcount() an. Siehe http://www.cplusplus.com/reference/istream/istream/gcount/.

HINWEIS: Ich war verwirrt mit boost::asio::read und boost::asio::ip::tcp::socket::read_some. Aber ihr Verhalten unterscheidet sich von std::istream.

ist der komplette Code der festen 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; 

}