使用 zlib 压缩 boost 二进制文件

compressing boost binary archive with zlib

我正在尝试压缩没有临时文件的序列化 boost 存档。我设法让它与一个临时的一起工作,所以我试图解决它的代码。

class MyClass {
public:
  int a;
  std::string b;
  template<class Archive> void serialize( Archive & arc, const unsigned int version ){
    arc & a & b;
  }
};

int main(){
  MyClass mc{ 4, "This is a somewhatishly long string." };

  std::ostringstream oss;
  boost::archive::binary_oarchive bo( oss );    
  bo << mc;

  std::ofstream ofs( "save.z", std::ios::out | std::ios::binary );
  boost::iostreams::filtering_ostreambuf fos;
  fos.push( boost::iostreams::zlib_compressor( boost::iostreams::zlib::best_compression ) );
  fos.push( bo );
  boost::iostreams::copy( fos, ofs );
}

问题是我在 fos.push(bo) 行遇到了两打模板编译错误。

我曾经在 Boost C++ Serialization overhead (see the comment and Live On Coliru).

的基准测试中添加了压缩

您可以将它们用作示例。

更新

我做了腿部工作。你扭转了一些事情。无论如何,您并不是真的想要 stringstream。 (见下文)

主程序

Live On Coliru

#include <boost/serialization/serialization.hpp>
#include <string>

struct MyClass {
    int a;
    std::string b;
    template <class A> void serialize(A &ar, unsigned) { ar & a & b; }

    bool operator==(MyClass const& other) const {
        return a == other.a && b == other.b;
    }
};

#include <iostream>

static inline std::ostream& operator<<(std::ostream& os, MyClass const& obj) {
    return os << "{ a:" << obj.a << ", b:'" << obj.b << "' }";
}

void save(MyClass const& obj, std::string const& fname);
MyClass load(std::string const& fname);

int main() {
    MyClass original{ 4, "This is a somewhatishly long string." };

    save(original, "save.z");
    auto roundtrip= load("save.z");

    std::cout << "original:\t"  << original << "\n";
    std::cout << "roundtrip:\t" << roundtrip << "\n";
    std::cout << "equal? "      << std::boolalpha << (original == roundtrip) << "\n";
}

输出为

original:   { a:4, b:'This is a somewhatishly long string.' }
roundtrip:  { a:4, b:'This is a somewhatishly long string.' }
equal? true

save.z 包含:

00000000: 78da 1363 8080 e2d4 a2cc c49c ccaa c492  x..c............
00000010: ccfc 3c2b abc4 a2e4 8ccc b254 0106 160e  ..<+.......T....
00000020: 160e 46a8 1a06 1620 5681 b243 3232 8b15  ..F.... V..C22..
00000030: 8028 51a1 383f 37b5 3c03 a8b1 3823 a752  .(Q.8?7.<...8#.R
00000040: 2127 3f2f 5da1 b8a4 2833 2f5d 0f00 a29a  !'?/]...(3/]....
00000050: 16b7                                     ..

保存代码

注意 streams/archive 得到 closed/flushed/destructed 的顺序。安全顺序是:

  • 构造fstream
  • 构造压缩器/过滤流
  • 在过滤流上构建存档
  • flush/close/destruct存档
  • flush/close/destruct 过滤流和压缩器
  • flush/close/destruct fstream
#include <boost/archive/binary_oarchive.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>

#include <sstream>
#include <fstream>

void save(MyClass const& obj, std::string const& fname) {
    std::ofstream ofs(fname, std::ios::binary);
    {
        boost::iostreams::filtering_ostreambuf fos;

        // push the ofstream and the compressor
        fos.push(boost::iostreams::zlib_compressor(boost::iostreams::zlib::best_compression));
        fos.push(ofs);

        // start the archive on the filtering buffer:
        boost::archive::binary_oarchive bo(fos);
        bo << obj;
    }
}

加载代码

基本上是相反的:

#include <boost/archive/binary_iarchive.hpp>
MyClass load(std::string const& fname) {
    std::ifstream ifs(fname, std::ios::binary);
    {
        boost::iostreams::filtering_istreambuf fis;

        // push the ifstream and the decompressor
        fis.push(boost::iostreams::zlib_decompressor());
        fis.push(ifs);

        // start the archive on the filtering buffer:
        boost::archive::binary_iarchive bi(fis);
        MyClass obj;
        bi >> obj;

        return obj;
    }
}