如何挂钩加速系列化和放大器; iostreams的序列化和放大器; gzip压缩的目的是字符串? [英] How to hook up Boost serialization & iostreams to serialize & gzip an object to string?

查看:276
本文介绍了如何挂钩加速系列化和放大器; iostreams的序列化和放大器; gzip压缩的目的是字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用升压序列化库,这实际上是pretty不错,并让我做简单封装到我的序列化对象保存为字符串,像这样:

 命名空间栏=的boost ::存档;
空间生物=的boost ::输入输出流;模板<类T>内联的std ::字符串saveString(常量T&放大器; O){
 的std :: ostringstream OSS;
 酒吧:: binary_oarchive OA(OSS);
 OA<< O;
 返回oss.str();
}
模板<类T>内嵌无效saveFile的(常量T&放大器; 0,为const char * FNAME){
 的std :: OFS的ofstream(FNAME,性病::内部监督办公室::出来|的std :: IOS ::二进制|性病:: IOS :: TRUNC);
 酒吧:: binary_oarchive OA(OFS);
 OA<< O;
}
模板<类T>内嵌无效的loadFile(T&安培; 0,为const char * FNAME){
 性病:: ifstream的IFS(FNAME,性病::内部监督办公室::在|的std :: IOS ::二进制);
 断言(ifs.good()); // XXX捕捉如果找不到文件
 酒吧:: binary_iarchive IA(IFS);
 IA>> O;
}

问题是,我刚刚发现需要COM preSS我的序列化数据,也因此我期待在这样做,在升压::输入输出流过滤器。我想通了如何使用文件做成功:

 模板<类T>内嵌无效saveGZFile(常量T&放大器; 0,为const char * FNAME){
 的std :: OFS的ofstream(FNAME,性病::内部监督办公室::出来|的std :: IOS ::二进制|性病:: IOS :: TRUNC);
 生物:: filtering_streambuf<生物::输出>出;
 out.push(升压::输入输出流:: gzip_com pressor());
 out.push(OFS);
 酒吧:: binary_oarchive OA(出);
 OA<< O;
}
模板<类T>内嵌无效loadGZFile(T&安培; 0,为const char * FNAME){
 性病:: ifstream的IFS(FNAME,性病::内部监督办公室::在|的std :: IOS ::二进制);
 断言(ifs.good()); // XXX捕捉如果找不到文件
 生物:: filtering_streambuf<生物::输入>在;
 in.push(生物:: gzip_decom pressor());
 in.push(IFS);
 酒吧:: binary_iarchive IA(中);
 IA>> O;
}

但无法弄清楚如何正确保存到一个COM pressed字符串。问题是,我不冲洗过滤器的链条,但我已经试过弹出和同步,并似乎没有任何工作。这里是我的破code:

 模板<类T>内联的std ::字符串saveGZString(常量T&放大器; O){
 的std :: ostringstream OSS;
 生物:: filtering_streambuf<生物::输出>出;
 out.push(生物:: gzip_com pressor());
 out.push(OSS);
 酒吧:: binary_oarchive OA(出);
 OA<< O;
 // XXX out.pop()两次? out.strict_sync()? oss.flush()?
 返回oss.str();
}

因此​​,一些数据卡在流缓冲的地方,我最后总是以com pressed数据AA几个完整的块(16K或32K),当我知道它应该是43K左右,考虑到(有效)输出我使用我的saveGZFile方法来获取。显然挂钩的关闭ofstream的刷新和正确,但挂接的ostringstream没有。

任何帮助吗? (这是我的第一个计算器的问题 - !帮帮我,伙计们,你是我唯一的希望)


解决方案

回到这个问题,我才意识到去年我一定是固定它的某个时候(因为我用saveGZString现在)

。挖看我怎么固定它,它是pretty傻/简单:

 命名空间栏=的boost ::存档;
空间生物=的boost ::输入输出流;模板< typename的T>内联的std ::字符串saveGZString(常量T&放大器; O){
        的std :: ostringstream OSS;
        {
                生物:: filtering_stream<生物::输出> F;
                f.push(生物:: gzip_com pressor());
                f.push(OSS);
                酒吧:: binary_oarchive OA(F);
                OA<< O;
        } // gzip_com pressor刷新当f超出作用域
        返回oss.str();
}

只是让整个链条超出范围和它的作品!整齐!这里是我的装载机的完整性:

 模板< typename的T>内嵌无效loadGZString(T&安培O,常量标准::字符串&安培; S){
        的std :: istringstream ISS(S);
        生物:: filtering_stream<生物::输入> F;
        f.push(生物:: gzip_decom pressor());
        f.push(ISS);
        酒吧:: binary_iarchive IA(F);
        IA>> O;
}

I've been using the Boost serialization library, which is actually pretty nice, and lets me make simple wrappers to save my serializable objects to strings, like so:

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

The thing is, I just found the need to compress my serialized data, too, so I'm looking at doing that with the filters in boost::iostreams. I figured out how to do it successfully with files:

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

But can't figure out how to save correctly to a compressed string. The problem is that I'm not flushing the chain of filters, but I've tried popping and syncing and nothing seems to work. Here's my broken code:

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();
}

As a result some data gets stuck in the stream buffer somewhere, and I always end up with a a few complete blocks (16K or 32K) of compressed data when I know it should be 43K or so given the (valid) output I get from using my saveGZFile method. Apparently hooking up the ofstream closes and flushes properly, but hooking up the ostringstream doesn't.

Any help? (This is my first stackoverflow question — help me, guys, you're my only hope!)

解决方案

Returning to this question, I realized I must've fixed it sometime last year (as I'm using saveGZString right now). Digging to see how I fixed it, it was pretty silly/simple:

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();
}

Just let the whole chain go out of scope and it works! Neat! Here's my loader for completeness:

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

这篇关于如何挂钩加速系列化和放大器; iostreams的序列化和放大器; gzip压缩的目的是字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆