簡體   English   中英

如何連接Boost序列化和iostreams來序列化和將對象gzip到字符串?

[英]How to hook up Boost serialization & iostreams to serialize & gzip an object to string?

我一直在使用Boost序列化庫,這實際上非常好,並且讓我使用簡單的包裝器將可序列化對象保存到字符串中,如下所示:

namespace bar = boost::archive;
namespace bio = boost::iostreams;

template <class T> inline std::string saveString(const T & o) {
 std::ostringstream oss;
 bar::binary_oarchive oa(oss);
 oa << o;
 return oss.str();
}
template <class T> inline void saveFile(const T & o, const char* fname) {
 std::ofstream ofs(fname, std::ios::out|std::ios::binary|std::ios::trunc);
 bar::binary_oarchive oa(ofs);
 oa << o;
}
template <class T> inline void loadFile(T & o, const char* fname) {
 std::ifstream ifs(fname, std::ios::in|std::ios::binary);
 assert(ifs.good()); // XXX catch if file not found
 bar::binary_iarchive ia(ifs);
 ia >> o;
}

問題是,我剛剛發現需要壓縮我的序列化數據,所以我正在考慮使用boost :: iostreams中的過濾器。 我想出了如何成功地使用文件:

template <class T> inline void saveGZFile(const T & o, const char* fname) {
 std::ofstream ofs(fname, std::ios::out|std::ios::binary|std::ios::trunc);
 bio::filtering_streambuf<bio::output> out;
 out.push(boost::iostreams::gzip_compressor());
 out.push(ofs);
 bar::binary_oarchive oa(out);
 oa << o;
}
template <class T> inline void loadGZFile(T & o, const char* fname) {
 std::ifstream ifs(fname, std::ios::in|std::ios::binary);
 assert(ifs.good()); // XXX catch if file not found
 bio::filtering_streambuf<bio::input> in;
 in.push(bio::gzip_decompressor());
 in.push(ifs);
 bar::binary_iarchive ia(in);
 ia >> o;
}

但無法弄清楚如何正確保存到壓縮字符串。 問題是我沒有沖洗過濾器鏈,但我嘗試了彈出和同步,似乎沒有任何工作。 這是我破碎的代碼:

template <class T> inline std::string saveGZString(const T & o) {
 std::ostringstream oss;
 bio::filtering_streambuf<bio::output> out;
 out.push(bio::gzip_compressor());
 out.push(oss);
 bar::binary_oarchive oa(out);
 oa << o;
 // XXX out.pop() twice?  out.strict_sync()??  oss.flush()??
 return oss.str();
}

結果一些數據卡在某個地方的流緩沖區中,當我知道它應該是43K左右時,我總是得到一些完整的塊(16K或32K)壓縮數據,因為我得到的(有效)輸出我的saveGZFile方法。 顯然連接正確的關閉和沖洗,但鈎住ostringstream不會。

有幫助嗎? (這是我的第一個stackoverflow問題 - 幫助我,伙計們,你們是我唯一的希望!)

回到這個問題,我意識到我必須在去年的某個時候修復它(因為我現在正在使用saveGZString)。 挖掘看我如何修復它,它非常愚蠢/簡單:

namespace bar = boost::archive;
namespace bio = boost::iostreams;

template <typename T> inline std::string saveGZString(const T & o) {
        std::ostringstream oss;
        { 
                bio::filtering_stream<bio::output> f;
                f.push(bio::gzip_compressor());
                f.push(oss);
                bar::binary_oarchive oa(f);
                oa << o;
        } // gzip_compressor flushes when f goes out of scope
        return oss.str();
}

只是讓整個鏈條超出范圍,它的工作原理! 整齊! 這是我的裝載完整性:

template <typename T> inline void loadGZString(T & o, const std::string& s) {
        std::istringstream iss(s);
        bio::filtering_stream<bio::input> f;
        f.push(bio::gzip_decompressor());
        f.push(iss);
        bar::binary_iarchive ia(f);
        ia >> o;
}

我自己沒有運行代碼,但我最好的猜測是使用out.strict_sync()flush()應用於管道中的每個filter / device 我似乎無法告訴,不過,如果gzip_compressorflushable 如果不是,則strict_sync()將返回false,而sync()將更合適。

暫無
暫無

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

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