c++序列化库cereal使用介绍
来源:互联网 发布:加入浙江网络作协 编辑:程序博客网 时间:2024/06/05 22:56
由来
一直以来没体会到序列化的好处,最近写了配置文件读写的类,搜索过程中发现用序列化的话可以很方便的存取,几行代码就能完成。
几种序列化库
C++上序列化的库没有c#或者java那么多,比较普遍的有2个:
1.google的protobuf库
2.boost的serialization库
它们都有各自的优势,但针对小型系统的配置文件存储的话都太大太笨重了,特别是boost的serialization库居然还要编译,几百M的库,编译要2个小时,不划算。
在github上搜索到一个cereal库,获得里高达715个star,而且虽然它不支持wstring宽格式字符,但可以使用中文作为string变量,因此是可以完美支持中文配置文件的。这里记录下它的使用。
cereal库使用
平台
注意cereal基于c++11,需要支持c++11的编译器。
下载解压
在文献3或者4里下载到压缩包,将里面的include文件夹解压缩出来,其他的不需要。
工程配置
新建win32控制台工程,将include文件夹放入工程目录里,并在项目-属性-c++引用目录里添加$(ProjectDir)include
代码
1.先来最简单的将基本数据类型保存为json文件。
引用库文件
#include <fstream>#include <iostream>#include <string>#include <cereal/archives/JSON.hpp>#include <cereal/types/vector.hpp>#include <cereal/types/string.hpp>
然后在main
里写
std::ofstream file("out.json"); cereal::JSONOutputArchive archive(file); std::string s[] = { "this is a string", " 中文string也是可以支持的" }; std::vector<double> vec = { 1.00001, 2e3, 30.1, -4, 5 }; archive(CEREAL_NVP(vec), CEREAL_NVP(s));
运行成功后结果为一个标准json文件
2.再来最简单的读取json文件到变量。
main里写
std::ifstream file("out.json"); cereal::JSONInputArchive archive(file); std::string s[2]; archive(CEREAL_NVP(s)); std::cout << s[1];
结果很完美,对中文字符和浮点数支持都很好,不愧是715个star的项目
3.稍微复杂点的自定义类写入json
定义一个结构并添加模板函数
struct Data{ int index = 1; double d[3] = { 1.0,2.33e-5,1000000.0 }; std::vector<std::string> vs; template <class Archive> void serialize(Archive & ar) { ar(index, d, vs); }};
在main
中
Data mydata; std::string s1 = "中文字符串/*-+!@#$%^&"; std::string s2 = "english/*-+!@#$%^&"; mydata.vs.push_back(s1); mydata.vs.push_back(s2); std::ofstream file("out.json"); cereal::JSONOutputArchive archive(file); archive(CEREAL_NVP(mydata));
结果同样符合预期
注意这里的项目-值对里的项目都是默认的value0-value2,并不是结构的变量名,如果想在json文件里保存到变量名,可以用下面的方法
archive(CEREAL_NVP(mydata.index), CEREAL_NVP(mydata.d), CEREAL_NVP(mydata.vs));
这样结果便是理想的形式了
4.稍微复杂点的从json读入自定义类的变量
和基本数据类型读取archive(CEREAL_NVP(s));
不一样了,如果这样写,那么cereal将会抛出一个json异常。因为NVP找不到该变量了。要用另外一个cereal的模板cereal::make_nvp
std::ifstream file("out.json"); cereal::JSONInputArchive archive(file); int n; std::vector<std::string> s; double d[3]; archive(cereal::make_nvp("mydata.index", n)); archive(cereal::make_nvp("mydata.d", d)); archive(cereal::make_nvp("mydata.vs", s)); std::cout << s[1] << '\t' << s[0] << '\t' << d[1];
便能正确读入这些变量了。
注意,保存的格式要为archive(CEREAL_NVP(mydata.index), CEREAL_NVP(mydata.d), CEREAL_NVP(mydata.vs));
时上面的代码才能正确读取。尝试了几次,按照archive(CEREAL_NVP(mydata));
反序列化时都会抛出异常,如果谁知道怎么正确读取请告诉我
4.嵌套的自定义类写入json
假设有如下结构
struct Dat{ int x; int y;};struct Data{ Dat dat = { 2,3 }; int index = 1; double d[3] = { 1.0,2.33e-5,1000000.0 }; std::vector<std::string> vs;};
想在保存的文件里,完整的存贮结构变量名,怎么办呢,方法如下:
struct Dat{ int x; int y; template <class Archive> void serialize(Archive & ar) { ar(cereal::make_nvp("x", x), cereal::make_nvp("y", y)); }};struct Data{ Dat dat = { 2,3 }; int index = 1; double d[3] = { 1.0,2.33e-5,1000000.0 }; std::vector<std::string> vs; template <class Archive> void serialize(Archive & ar) { ar(cereal::make_nvp("Dat", dat), cereal::make_nvp("index", index), cereal::make_nvp("d", d), cereal::make_nvp("vs", vs)); }};
序列化保存的时候
Data mydata; mydata.dat.x = 50; mydata.dat.y = 150; std::string s1 = "中文字符串/*-+!@#$%^&"; std::string s2 = "english/*-+!@#$%^&"; mydata.vs.push_back(s1); mydata.vs.push_back(s2); std::ofstream file("out.json"); cereal::JSONOutputArchive archive(file); archive(cereal::make_nvp("mydata", mydata));
反序列化读取的时候
std::ifstream file("out.json"); cereal::JSONInputArchive archive(file); Data mydata; archive(cereal::make_nvp("mydata", mydata));//要修改某个配置的时候 mydata.index = 45;//再序列化回去 std::ofstream file2("out.json"); cereal::JSONOutputArchive archive2(file2); archive2(cereal::make_nvp("mydata", mydata));
结果如图:
参考文献
1.使用C++进行对象序列化
2.最常用的两种C++序列化方案的使用心得(protobuf和boost serialization
3.cereal
4.cereal quickstart
- c++序列化库cereal使用介绍
- Cereal library--序列化类型
- cereal:C++实现的开源序列化库
- Cereal library--一个C++11的序列化库
- 介绍Java对象序列化使用基础
- C的序列化库tpl的使用
- java序列化介绍
- Net序列化介绍
- php 中序列化和json使用介绍_PHP教程
- Cereal library--快速入门
- Cereal library--Serialization函数
- [C#] 使用 DataContractJsonSerializer 序列化 反序列化
- 【从CSLA中学C#】3 序列化的使用
- google protocol buffer (C++,Java序列化使用实例)
- google protocol buffer (C++,Java序列化使用实例)
- google protocol buffer (C++,Java序列化使用实例)
- google protocol buffer (C++,Java序列化使用实例)
- google protocol buffer (C++,Java序列化使用实例)
- perl内置警告信息
- SQL truncate 、delete与drop区别
- js防止表单重复提交
- UIBarButtonSystemItemFixedSpace
- 在Vim中使用ctags
- c++序列化库cereal使用介绍
- libcurl出现CURLcode 23 CURLE_WRITE_ERROR错误 以及每次抓取网页长度不一致问题
- 怎么查看Navicat Premium 中的日志文件
- android音乐播放器Media
- 数据字典的范例
- iOS时间类型转换和各种数据类型进行转换
- Android多线程-------同步辅助类
- 二叉树的深度优先遍历与广度优先遍历 [ C++ 实现 ]
- Java Web 使用getPart()、getParts()上传文件