背景
在开发硬件产品时,会有一些参数配置文件,为了保密性或者传输,需要对其序列化处理,待到产品读取文件时,进行反序列化解码转化为设定的参数类型。
简介
ceral是一个仅包含头文件的C++序列化库,可以将任意的数据类型,转化为二进制编码、XML或者JSON。ceral具有轻量、快速、易扩展的特性,不依赖于其他任何库。
cereal 提供了对标准库中几乎所有类型的序列化支持,并且开箱即用。cereal 还完全支持继承和多态。由于 cereal 被设计为一个最小且快速的库,它并不像 Boost 等其他序列化库那样执行相同级别的对象跟踪。因此,它不支持裸指针和引用,但智能指针(如 std::shared_ptr 和 std::unique_ptr)没有问题。
如何使用
#include <cereal/types/unordered_map.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/archives/binary.hpp>
#include <fstream>// 定义一个结构体MyRecord,用于存储记录
struct MyRecord
{uint8_t x, y; // 两个无符号8位整数float z; // 一个浮点数// 序列化函数模板,用于序列化和反序列化MyRecord对象template <class Archive>void serialize( Archive & ar ){ar( x, y, z ); // 将x, y, z序列化或反序列化}
};// 定义一个结构体SomeData,用于存储更复杂的数据
struct SomeData
{int32_t id; // 一个32位整数,用于标识std::shared_ptr<std::unordered_map<uint32_t, MyRecord>> data; // 一个智能指针,指向一个unordered_map,存储uint32_t键和MyRecord值// 序列化函数模板,用于序列化SomeData对象template <class Archive>void save( Archive & ar ) const{ar( data ); // 序列化data成员}// 序列化函数模板,用于反序列化SomeData对象template <class Archive>void load( Archive & ar ){static int32_t idGen = 0; // 一个静态局部变量,用于生成idid = idGen++; // 每次反序列化时,id自增并赋值给当前对象ar( data ); // 反序列化data成员}
};int main()
{// 创建一个ofstream对象,用于写入文件,以二进制模式打开std::ofstream os("out.cereal", std::ios::binary);// 创建一个cereal的二进制输出存档对象cereal::BinaryOutputArchive archive( os );// 创建SomeData对象SomeData myData;// 将myData对象序列化到存档中archive( myData );return 0; // 程序结束
}
举一些简单的例子:
- 保存如下的用户参数。
bool bIsValid = true;
int a = 1;
float b = 3.11;
double c = 4.3333;
#include "cereal/types/unordered_map.hpp"
#include "cereal/types/memory.hpp"
#include "cereal/archives/binary.hpp"
#include <fstream>
#include <sstream>template <class T>
void save(cereal::BinaryOutputArchive & archive, const std::string & str_name, const T value)
{archive(str_name);archive(value);std::stringstream s;s << std::endl;archive(s.str());
}template <class T>
void load(std::string & str_name, T & value, cereal::BinaryInputArchive & archive)
{archive(str_name);archive(value);std::string str;archive(str);
}void main()
{// 序列化保存为params二进制文件std::string str_file_name = "params";std::ofstream os(str_file_name , std::ios::binary);cereal::BinaryOutputArchive archive(os);save(archive, "bIsValid ", bool(true));save(archive, "a", (int)1);save(archive, "b", (float)3.11);save(archive, "c", (double)4.3333);os.close();// 加载该文件std::ifstream is(str_file_name , std::ios::binary);cereal::BinaryInputArchive inputArchive(is);std::string str_name;bool bIsValid;load(str_name, bIsValid, inputArchive);std::cout << str_name << " " << bIsValid << std::endl;int a;load(str_name, a, inputArchive);std::cout << str_name << " " << a << std::endl;float b;load(str_name, b, inputArchive);std::cout << str_name << " " << b << std::endl;double c;load(str_name, c, inputArchive);std::cout << str_name << " " << c << std::endl;
}