使用Boost的Serialization库序列化STL标准容器
? ? ? ? 使用Boost做對象序列化是非常方便的,本文將介紹一種序列化STL標準容器的方法。
? ? ? ? 這是之前設計的異步框架的一個子功能:過程A將標準容器數據序列化成二進制流,然后將該二進制數據發送到過程B,過程B將數據反序列化為標準容器。(轉載請指明出于breaksoftware的csdn博客)
? ? ? ? 下面這個基類支持vector、set、unordered set、multiset、unordered multiset、map、unordered map、multimap和unordered multimap。
/*************************************************************************> File Name: serialization.h> Author: fangliang> Mail: fangliang1988@gmail.com > Created Time: Fri 23 Mar 2018 03:11:14 PM CST************************************************************************/
#ifndef STLSERIALIZATION_SERIALIZATION_H
#define STLSERIALIZATION_SERIALIZATION_H#include <string>
#include <sstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp> namespace stl_serialization {template<class T>
class Serialization : public T {
public:void serialization(std::ostringstream& ostream) {boost::archive::binary_oarchive oa(ostream);oa << *this;}void unserialization(std::istringstream& istream) {boost::archive::binary_iarchive ia(istream);ia >> *this;}
private: friend class boost::serialization::access; template<class Archive> void serialize(Archive& ar, const unsigned int version) { ar & boost::serialization::base_object<T>(*this); }
};}#endif // STLSERIALIZATION_SERIALIZATION_H
? ? ? ? 可被序列化的標準容器只要繼承該基類即可。以map為例
/*************************************************************************> File Name: map_serialization.h> Author: fangliang> Mail: fangliang1988@gmail.com > Created Time: Thu 22 Mar 2018 11:09:11 PM CST************************************************************************/
#ifndef STLSERIALIZATION_MAP_SERIALIZATION_H
#define STLSERIALIZATION_MAP_SERIALIZATION_H#include <map>
#include <string>
#include <sstream>
#include <boost/serialization/map.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>#include "serialization.h"namespace stl_serialization {template<class T, class T1>
class MapSerialization : public Serialization<std::map<T, T1> > {
};}#endif // STLSERIALIZATION_MAP_SERIALIZATION_H
? ? ? ? 使用一個單元測試來測試這段代碼
/*************************************************************************> File Name: ut_map_serialization.cpp> Author: fangliang> Mail: fangliang1988@gmail.com > Created Time: Thu 22 Mar 2018 11:11:46 PM CST************************************************************************/
#include "gtest/gtest.h"
#include "./src/stl_serialization/map_serialization.h"using stl_serialization::MapSerialization;int main(int argc, char* argv[]) {testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}namespace unit_test {class UtMapSerialization :public ::testing::Test
{
protected:virtual void SetUp() {MapSerialization<int, std::string> ms_src;for (int i = 0; i < _size; i++) {ms_src[i] = " ";}ms_src.serialization(_ost);}virtual void TearDown() {}
protected:int _size = 10000;std::ostringstream _ost;
};TEST_F(UtMapSerialization, SizeEq) {MapSerialization<int, std::string> ms_des;std::istringstream ist(_ost.str());ms_des.unserialization(ist);ASSERT_EQ(_size, ms_des.size());
}TEST_F(UtMapSerialization, ElemEq) {MapSerialization<int, std::string> ms_des;std::istringstream ist(_ost.str());ms_des.unserialization(ist);int i = 0;for (std::map<int, std::string>::iterator it = ms_des.begin(); it != ms_des.end(); it++) {ASSERT_EQ(it->first, i++);}
}}
? ? ? ? 如果STL的容器中存放在的是一個非標準類型,比如一個用戶自定義類型,則需要讓該類型實現serialize方法。以vector為例
/*************************************************************************> File Name: vector_serialization.h> Author: fangliang> Mail: fangliang1988@gmail.com > Created Time: Thu 22 Mar 2018 03:41:16 PM CST************************************************************************/
#ifndef STLSERIALIZATION_VECTOR_SERIALIZATION_H
#define STLSERIALIZATION_VECTOR_SERIALIZATION_H#include <vector>
#include <string>
#include <sstream>
#include <boost/serialization/vector.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp> #include "serialization.h"namespace stl_serialization {template<class T>
class VectorSerialization : public Serialization<std::vector<T> > {
};}#endif // STLSERIALIZATION_VECTOR_SERIALIZATION_H
? ? ? ? 下面代碼中,由于TestData是容器承載的類型,所以它需要增加24~33行代碼用于容器內對象序列化。
/*************************************************************************> File Name: ut_vecotr_serialization.cpp> Author: fangliang> Mail: fangliang1988@gmail.com > Created Time: Wed 21 Mar 2018 02:34:18 PM CST************************************************************************/
#include "gtest/gtest.h"
#include "./src/stl_serialization/vector_serialization.h"using stl_serialization::VectorSerialization;int main(int argc, char* argv[]) {testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}namespace unit_test {struct TestData {int interger;double db;float fl;std::string str;
private: friend class boost::serialization::access; template<class Archive> void serialize(Archive& ar, const unsigned int version) { ar & interger;ar & db;ar & fl;ar & str;}
};class UtVectorSerialization :public ::testing::Test
{
protected:virtual void SetUp() {VectorSerialization<int> vs_src;for (int i = 0; i < _size; i++) {TestData item;item.interger = i;item.db = i;item.fl = i;item.str = std::to_string(i);vs_src.push_back(item);}vs_src.serialization(_ost);}virtual void TearDown() {}
protected:int _size = 10000;std::ostringstream _ost;
};TEST_F(UtVectorSerialization, SizeEq) {VectorSerialization<int> vs_des;std::istringstream ist(_ost.str());vs_des.unserialization(ist);ASSERT_EQ(_size, vs_des.size());
}TEST_F(UtVectorSerialization, ElemEq) {VectorSerialization<int> vs_des;std::istringstream ist(_ost.str());vs_des.unserialization(ist);for (int i = 0; i < _size; i++) {const TestData& item = vs_des.at(i);ASSERT_EQ(item.interger, i);ASSERT_DOUBLE_EQ(item.db, i);ASSERT_FLOAT_EQ(item.db, i);std::string str = std::to_string(i);ASSERT_STREQ(item.str.c_str(), str.c_str()); }
}}
? ? ? ? 最后我們看下包含10000個對象的容器反序列化耗時,總體來說效率還是不錯的。
? ? ? ? 最后說下,unordered set、unordered multiset、unordered map和unordered multimap等不保證序列化前后容器中元素順序一致。
總結
以上是生活随笔為你收集整理的使用Boost的Serialization库序列化STL标准容器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++拾趣——有趣的操作符重载
- 下一篇: 堆状态分析的利器——valgrind的D