背景
在开发硬件产品时,会有一些参数配置文件,为了保密性或者传输,需要对其序列化处理,待到产品读取文件时,进行反序列化解码转化为设定的参数类型。
简介
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; // 一个静态局部变量,用于生成id
id = 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;
}