2017-06-21 98 views
0

我正在使用boost iostreams(1.64.0)來解壓縮zlib數據。 我想做流式解壓。這意味着壓縮數據的大小是不可預測的。 我寫了下面的代碼示例。如何使用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; 

} 

我用readsome()因爲數據的大小是不可預知的。 我得到了以下的輸出:

read_size:0 
rdstate:0 

這是意外的我。

如果我使用getline()代替readsome(),我得到了以下的輸出:

rdstate:2 
Hello World 

據預計輸出。

我認爲當我使用readsome()時,輸出應該是相同的。 我不能在實際的代碼中使用getline(),因爲原始數據是二進制格式。

有沒有什麼辦法可以使用readsome()filtering_streambuf或任何好的方法來解壓縮不可預知的長度的二進制數據?

+1

爲什麼不使用'閱讀()'代替 – sehe

+1

謝謝你的評論。我意識到我誤解了'istream :: read()'和'istream :: readsome()'就像'boost asio'的'read()'和'socket :: read_some()'一樣。 我取代 '的std ::爲size_t read_size = is.readsome(BUF,buf_size);'' 的std :: COUT << 「read_size:」 << read_size <<的std :: ENDL;' 與 '是。read(buf,buf_size);' 'std :: size_t read_size = is.gcount();' 'std :: cout <<「read_size:」<< read_size << std :: endl;' then my代碼工作正如我所料。 –

回答

0

感謝sehe's comment,問題解決了。

我寫了the response的評論,但它很難閱讀,因爲代碼格式不正確。所以我自己回答。我希望這會對其他有類似問題的人有所幫助。

我更換

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

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

,那麼問題就解決了。

我誤解了std::istream::read塊直到讀取buf_size長度數據。這不是真的。即使實際讀取大小小於buf_size,函數也會返回。請參閱http://www.cplusplus.com/reference/istream/istream/read/。爲了得到read_size,我打電話給std::istream::gcount()。請參閱http://www.cplusplus.com/reference/istream/istream/gcount/

注:我已經與boost::asio::readboost::asio::ip::tcp::socket::read_some混淆。但他們的行爲不同於std::istream的行爲。

這裏是固定版本的完整代碼:

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

}