zoukankan      html  css  js  c++  java
  • C++ | boost库 类的序列化

    是的,这是今年的情人节,一篇还在研究怎么用的文章,文结的时候应该就用成功了. 恩,要有信心

    神奇的分割线


    不知何时装过boost库的header-only库, 所以ratslam中的boost是可以编译的,但是我自己试的程序会编译不过, 提示错误是未定义的引用. 所以我就从安装boost库开始.

    1. 到www.boost.org下载相应的库, 目前最新是1_60_0版本的链接打开

    文件有点大


    下载好后就可以安装了.

    1. 我将文件解压缩在home目录下命名为BOOST_ROOT目录下.

    2. cd BOOST_ROOT

    3. ./bootstrap.sh  --help

    4. ./bootstrap.sh  --prefix=/usr/local      ##其实默认情况下prefix的值就是/usr/local

    这句命令编译可执行文件到/usr/local目录下了,因此后面当你在程序中需要引用头文件依赖时,就在这个路径下

    编译会有点慢. 编译完成后会生成bjam可执行文件

    5. 编译完成后,安装bjam  ./bjam install


    安装完成,可以测试一下以下代码能否成功编译:

    demo.cpp

    #include <iostream>
    #include <string>
    #include <sstream>
    
    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    
    #include <boost/archive/binary_iarchive.hpp>
    #include <boost/archive/binary_oarchive.hpp>
    
    using namespace std;
    
    class Test
    {
    public:
    
     friend class boost::serialization::access;
    
     Test(bool b, char ch, int i, double d, string str)
      : m_bool(b), m_char(ch), m_int(i), m_double(d), m_str(str)
     {
     }
    
     template<class Archive>
     void serialize(Archive & ar, const unsigned int version)
     {
      ar& m_bool;
      ar& m_char;
      ar& m_int;
      ar& m_double;
      ar& m_str;
     }
    
    private:
     bool m_bool;
     char m_char;
     int m_int;
     double m_double;
     string m_str;
    };
    
    int main()
    {
     Test test(true, 'm', 50, 17.89, "fuzhijie");
    
     stringstream binary_sstream;
     stringstream text_sstream;
    
     long long begin, end;
    
     int size;
    
     //使用二进制的方式序列化
     boost::archive::text_oarchive text_oa(text_sstream);
     boost::archive::binary_oarchive binary_oa(binary_sstream);
    
     begin = time(NULL);
     for(int i = 0; i < 1000000; ++i)
     {
      text_oa << test;
     }
     end = time(NULL);  //哈,这里时间还可以这样用来计算程序执行时间,Mark
    
     size = text_sstream.tellp() / (1024 * 1024);
    
     cout << "text serialization seconds: " << end - begin << ", space: " << size << endl;
    
     begin = time(NULL);
     for(int i = 0; i < 1000000; ++i)
     {
      binary_oa << test;
     }
     end = time(NULL);
    
            //以MB为单位
     size = binary_sstream.tellp() / (1024 * 1024);
    
     cout << "binary serialization seconds: " << end - begin << ", space: " << size << endl;
    
     return 0;
    };

    编译:

    g++ -o main demo.cpp -L/usr/local/lib -lboost_serialization

    运行:

    ./main

    会看到执行结果:

    text serialization seconds: 1, space: 37
    binary serialization seconds: 0, space: 28

    安装成功!


    程序解读:

     首先,我用的序列化通篇都是嵌入式实现的. (机智的你一定在之前了解过序列化的嵌入式和非嵌入式的区别了)

     用serialist的时候的一般步骤是:

      1 先引用头文件, 

      2 在类的声明中, 你需要一个序列化函数,该函数的一般格式是:

     template<class Archive>
     void serialize(Archive & ar, const unsigned int version)
     {                                        //version是版本号
      ar& m_str;
     }

               这样声明了你要序列化的数据之后, 你就完成了一半了

      3 使用时是这样的, 因为你是要存储真实的数据,而类里面的声明只是告诉程序去序列化哪些变量. 因此, 首先你需要一个类的实例, 对象的创建过程中, 可以在任何时候给它的变量赋值,文上的程序是在初始化列表赋值的. 

       当你有了一个对象时, 你就有了明确要保存的数据了

      4 定义一个序列化的对象

    boost::archive::text_oarchive text_oa(text_sstream);//文本方式
    boost::archive::binary_oarchive binary_oa(binary_sstream);//二进制方式

      文末附: 何时用文本方式何时用二进制文件

      5 定义了序列化对象, 就可以将数据流写入了

    binary_oa << test;    //将对象test的序列化数据以二进制存储形式写入内存

      这样, 一个数据的序列化程序就完成了. 但是对于我这个还在学习C++的人来说, 似乎对容器和模板的操作没有很熟练啊, 如果要想序列化STL容器该怎么办呢?

     序列化STL容器

    #include<boost/serialization/list.hpp>
    class bus_route
    {
        friend class boost::serialization::access;
        std::list<bus_stop> stop;
        template<class Archive>
        void serialize(Archive &ar, const unsigned int version)
        {
            ar & stop;        //会自动加上容器的长度
        }
    public:
        bus_route(){}
    };

    这样序列化的声明就完成了

    使用时,在主函数中

    {
        std::ofstream ofs( "store.dat" );
        boost::archive::text_oarchive ar(ofs);
    
        ar & lv;    //lv是你上面声明序列化的那个类的对象
        ofs.close();
    }

    ps:序列化写完之后要用到FOREACH遍历一遍vector template, 记得是自己用的第一个或者第二个boost函数有些笔记的,然很开心来找,发现只有个标题的草稿,真想抽死自己,这个写完去填foreach的坑呀

     附: 二进制文件文本文件的选择

    1、二进制文件是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放,也就是说存放的是数据的原形式。

    2、文本文件是把数据的终端形式的二进制数据输出到磁盘上存放,也就是说存放的是数据的终端形式。

    一、如果要存储字符数据,无论是放在文本文件还是放在二进制文件中都和内存中的数据形式是没有区别的.同样也和终端形式没有区别。那么在存储和显示的特性上也没有任何区别,不浪费存储空间也不浪费转换时间。所以如果一个文件只存放字符数据,那么讨论该文件是用文本文件或是二进制文件是没有任何意义的。

    二、如果要存储非字符数据,则情况要复杂一些。

    1、如果您需要频繁地保存和访问数据.那么应该采用二进制文件进行存放,这样可以节省存储空间和转换时间。

    2、如果您需要频繁地向终端显示数据或从终端读人数据,那么应该采用文本文件进行存放,这样可以节省转换时间。windows中文本方式写时,存在'' ''->'' ''的转换,而二进制方式无转换.文本方式读时存在'' ''->至'' ''的转换,而二进制方式无转换.

    linux中文本方式的读写与二进制方式的读写无差别,不存在回车换行间的转换这样当直接在windows和linux中共享文件时,将会出现与回车换行相关的问题

  • 相关阅读:
    C# SQLiteHelper
    C# 自定义等待窗口
    C# Work PPT to PDF
    SQL 分隔字符串
    SQL 客户端查看
    SQL 自定义四舍五入
    SQL 并联更新
    C# 委托简单例子
    每天一个Linux命令(52)telnet命令
    每天一个Linux命令(51)ss命令
  • 原文地址:https://www.cnblogs.com/feixiao5566/p/5189246.html
Copyright © 2011-2022 走看看