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中文本方式寫時,存在''\n''->''\r\n''的轉換,而二進制方式無轉換.文本方式讀時存在''\r\n''->至''\n''的轉換,而二進制方式無轉換.

linux中文本方式的讀寫與二進制方式的讀寫無差別,不存在回車換行間的轉換這樣當直接在windows和linux中共享文件時,將會出現與回車換行相關的問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM