cereal:支持C++11的开源序列化库

cereal:支持C++11的开源序列化库

文章目录

  • 一:引言
  • 二、cereal简介
  • 三、cereal的下载和使用

一:引言

序列化 (Serialization)

程序员在编写应用程序的时候往往需要将程序的某些数据存储在内存中,然后将其写入某个文件或是将它传输到网络中的另一台计算机上以实现通讯。这个将程序数据转化成能被存储并传输的格式的过程被称为“序列化”(Serialization),而它的逆过程则可被称为“反序列化” (Deserialization)。

值得推荐的开源C/C++框架和库:https://www.cnblogs.com/lidabo/p/5514155.html

二、cereal简介

cereal是一个开源的(BSD License)、轻量级的、支持C++11特性的、仅仅包含头文件实现的、跨平台的C++序列化库。它可以将任意的数据类型序列化成不同的表现形式,比如二进制、XML格式或JSON。cereal的设计目标是快速、轻量级、易扩展——它没有外部的依赖关系,而且可以很容易的和其他代码封装在一块或者单独使用。

cereal支持标准库的几乎每一个类型的序列化。cereal也完全支持继承和多态。由于cereal被设计为一个精简、快速的库,它不像其他序列化库(比如Boost)在同一层次上会进行对象跟踪,这也导致了它不支持原始指针(raw pointer)和引用,但是智能指针(比如std::shared_ptr和std::unique_ptr)是没有问题的。

cereal适用于基于C++11标准的各种编译器

cereal使用了一些C++11的新特性,因此需要一个兼容性更好的的C++编译器才能正常工作。已被验证可用的编译器有g++4.7.3、clang++3.3、MSVC2013,或者更新版本。

它也可能可以在老版本编译器上工作,但并不保证完全支持。当使用g++或clang++编译器时,cereal同时需要libstdc++和libc++库。

cereal:更快速,更好的压缩
在简单的性能测试中,cereal通常比Boost的序列化库速度更快,而且产生的二进制形式占用更少的空间,尤其是针对更小的对象。cereal使用了C++中的速度最快的XML和JSON解析器和包装器。

cpp-serializers 这个项目中,作者对比了目前常见的序列化库:
在这里插入图片描述

可视化的模型对比
在这里插入图片描述

平均时间
在这里插入图片描述

可以看到,cereal在大小和时间上都有不错的表现(其实yas的速度好像更快,回头评测一下。。)

cereal是易于使用的

在代码增加cereal序列化功能可以简化为包含一个头文件,写一个序列化函数。无论是从概念上还是代码层次上,cereal的功能都是自文档化的。
如果你使用错误,cereal尽可能的在编译期触发静态断言。

对于Boost使用者来说,cereal提供了相似的语法,如果你使用过Boost的序列化库,你会发现cereal的语法看起来很熟悉。

如果你是从Boost转向使用cereal,一定要阅读这个过渡指南:http://uscilab.github.io/cereal/transition_from_boost.html

三、cereal的下载和使用

cereal的官方下载地址为:http://uscilab.github.io/cereal/index.html

编译源码过程很简单,在此不详述(注意源码解压在全英文路径下进行编译,不然出现编译失败的错误)。

使用cmake工具对源码进行编译和安装,选择对应版本的编译器和x86/x64选项,最终释放出一系列头文件到安装路径:


在这里插入图片描述

将cereal文件夹拷贝到指定位置,并设置系统环境变量为头文件所在路径,如:“D:\3rdLib\cereal\include”。

接下来就可以使用cereal库了~

我这里给他封装成了两个头文件:ConfigFile.h和ConfigComm.h

ConfigFile.h:

#ifndef _ConfigFile_Head_File_
#define _ConfigFile_Head_File_#include <cereal/archives/json.hpp>
#include <fstream>
#include "ConfigComm.h"template<typename DataType>
class ConfigFile
{
public:int SetConfigFile(std::string configFile){_configFile = configFile;std::ifstream f(_configFile);if (f.good() == true){_fileExist = true;return 1;}_errMsg = "配置文件 \"" + _configFile + "\" 不存在";return -1;}int Load(){if (_fileExist == false){_errMsg = "配置文件 \"" + _configFile + "\" 不存在";return -1;}try{std::ifstream is(_configFile);cereal::JSONInputArchive ar(is);ar(_data);}catch (CerealError err){_errMsg = "配置文件 \"" + _configFile + "\" " + err.errMsg;return -1;}catch (...){_errMsg = "配置文件 \"" + _configFile + "\" 存在错误";return -1;}return 1;}int Save(){if (_configFile.empty() == true){_errMsg = "配置文件路径为空";return -1;}try{std::ofstream os(_configFile);cereal::JSONOutputArchive ar(os);ar(cereal::make_nvp("配置信息", _data));}catch (...){_errMsg = "配置文件 \"" + _configFile + "\" 保存失败";return -1;}return 1;}int Load(std::string filename){if (SetConfigFile(filename) > 0)return Load();return -1;}int Save(std::string filename){_configFile = filename;return Save();}DataType& Data(){return _data;}private:bool _fileExist = false;std::string _configFile;DataType _data;public:std::string GetLastErrorMsg() { return _errMsg; }protected:std::string _errMsg;
};struct FileListConfig
{std::vector<std::string> lst;template<class Archive>void serialize(Archive& archive){CustomCereal(archive, "配置文件列表", lst);}
};template<typename DataType>
class ConfigFileList
{
public:int SetListConfigFile(std::string listConfigFile){_listConfigFile = listConfigFile;ConfigFile<FileListConfig> flc;if (flc.SetConfigFile(_listConfigFile) > 0){_fileExist = true;if (flc.Load() > 0){_cfList.clear();for (std::string filename : flc.Data().lst){ConfigFile<DataType> configFile;if (configFile.SetConfigFile(filename) > 0){_cfList.push_back(configFile);}else{_errMsg = configFile.GetLastErrorMsg();return -1;}}}else{_errMsg = flc.GetLastErrorMsg();return -1;}return 1;}_errMsg = "列表配置文件 \"" + _listConfigFile + "\" 不存在";return -1;}int Load(){if (_fileExist == false){_errMsg = "列表配置文件 \"" + _listConfigFile + "\" 不存在";return -1;}for (ConfigFile<DataType>& configFile : _cfList){if (configFile.Load() < 0){_errMsg = configFile.GetLastErrorMsg();return -1;}}if (_cfList.size() == 0){_errMsg = "列表配置文件 \"" + _listConfigFile + "\" 列表数据为空";return  -1;}return 1;}int Save(){if (_cfList.size() == 0){_errMsg = "列表配置文件 \"" + _listConfigFile + "\" 保存数据为空";return -1;}for (ConfigFile<DataType>& configFile : _cfList){if (configFile.Save() < 0){_errMsg = configFile.GetLastErrorMsg();return -1;}}return 1;}int Load(std::string listConfigFile){if (SetListConfigFile(listConfigFile) > 0)return Load();return -1;}int Save(std::string listConfigFile){_listConfigFile = listConfigFile;	ConfigFile<FileListConfig> flc;if (flc.SetConfigFile(_listConfigFile) > 0){if (flc.Load() > 0){for (std::string filename : flc.Data().lst){ConfigFile<DataType> configFile;if (configFile.Save(filename) < 0){_errMsg = configFile.GetLastErrorMsg();return -1;}}}else{_errMsg = flc.GetLastErrorMsg();return -1;}return 1;}_errMsg = flc.GetLastErrorMsg();return -1;}int Size(){return _cfList.size();}DataType& operator[](int index){return _cfList[index].Data();}private:bool _fileExist = false;std::string _listConfigFile;std::vector<ConfigFile<DataType>> _cfList;public:std::string GetLastErrorMsg() { return _errMsg; }protected:std::string _errMsg;
};#endif//_ConfigFile_Head_File_

ConfigComm.h

#ifndef _ConfigComm_Head_File_
#define _ConfigComm_Head_File_#include <cereal/types/base_class.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/array.hpp>
#include <cereal/types/map.hpp>struct CerealError
{CerealError(std::string err){errMsg = err;}std::string errMsg = "";
};template<class Archive, typename valueType>
void CustomCereal(Archive& archive, std::string itemName, valueType& value, bool canIgnore = false)
{try{archive(cereal::make_nvp(itemName, value));}catch (...){if (canIgnore == false){std::string msg = itemName + " 错误";throw CerealError(msg);}}
}template<typename Type>
static void CerealOutputFile(std::string fileName, std::string rootName, Type data)
{try{std::ofstream os(fileName);cereal::JSONOutputArchive ar(os);ar(cereal::make_nvp(rootName, data));}catch (...){}
}template<typename Type>
static Type CerealInputFile(std::string fileName, std::string rootName)
{Type data;try{std::ifstream is(fileName);cereal::JSONInputArchive ar(is);ar(cereal::make_nvp(rootName, data));}catch (...){}return data;
}template<typename Type>
static std::string CerealOutputString(Type data)
{std::ostringstream os;try{cereal::JSONOutputArchive ar(os);ar(CEREAL_NVP(data));}catch (...){return "";}std::string s = os.str();return 	s;
}template<typename Type>
static bool CerealInputString(std::string str, Type &data)
{try{std::istringstream is(str);cereal::JSONInputArchive ar(is);ar(CEREAL_NVP(data));return 	true;}catch (std::exception ex){return 	false;}
}class IConfigBase
{
public:virtual ~IConfigBase() = default;virtual int LoadConfig(std::string configFile) = 0;virtual int UpdateConfig() = 0;virtual int SaveConfig() = 0;virtual void* GetConfigData() = 0;virtual void* GetConfigPanel(int panelMode = 0) = 0;
};#endif//_ConfigComm_Head_File_

创建实例Test测试:

// CerealTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include "ConfigFile.h"struct NetConfig
{bool bWireEnable = false;int telePort = 12345;int cmdPort = 12345;template<class Archive>void serialize(Archive& archive){CustomCereal(archive, "是否为无线网络", bWireEnable);CustomCereal(archive, "遥测端口", telePort);CustomCereal(archive, "命令端口", cmdPort);}
};int main()
{ConfigFile<LogConfig> NetConfig;bool t1 = NetConfig.Load("LogConfig.json");bool t2 = NetConfig.Save();int  x = NetConfig.Data().cmdPort;std::cout << t1 << t2 << x;  
}

具体实例和库代码可在此下载:https://download.csdn.net/download/cao_jie_xin/88380290

参考:https://zhuanlan.zhihu.com/p/391610360
https://blog.csdn.net/qq_21950929/article/details/105745509

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/150787.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

互联网图片安全风控实战训练营开营!

内容安全风控&#xff0c;即针对互联网产生的海量内容的外部、内部风险做宏观到微观的引导和审核&#xff0c;从内容安全领域帮助企业化解监管风险和社会舆论风险&#xff0c;其核心是识别文本、图片、视频、音频中的有害内容。 由于互联网内容类型繁杂、多如牛毛&#xff0c;加…

JVM技术文档--JVM诊断调优工具Arthas--阿里巴巴开源工具--一文搞懂Arthas--快速上手--国庆开卷!!

​ Arthas首页 简介 | arthas Arthas官网文档 Arthas首页、文档和下载 - 开源 Java 诊断工具 - OSCHINA - 中文开源技术交流社区 阿丹&#xff1a; 之前聊过了一些关于JMV中的分区等等&#xff0c;但是有同学还是在后台问我&#xff0c;还有私信问我&#xff0c;学了这些…

三维模型3DTile格式轻量化的纹理压缩和质量关系分析

三维模型3DTile格式轻量化的纹理压缩和质量关系分析 在三维模型的3DTile格式轻量化处理中&#xff0c;纹理压缩是一个重要环节。但是&#xff0c;纹理压缩和模型质量之间存在明显的关系需要权衡。以下是纹理压缩和模型质量关系的详细分析&#xff1a; 1、压缩率与纹理质量&…

【UE】在游戏运行时,通过选择uasset来生成静态网格体

目录 主要流程 步骤 一、创建用于包含静态网格体的Actor蓝图 二、按钮点击事件 效果 主要流程 用户点击按钮后产生一个文件对话框&#xff0c;用户通过文件对话框选择指定的文件夹&#xff0c;我们获取到这个文件夹路径后处理成“按路径获取资产”节点所需的输入&#x…

【开发篇】二十、SpringBoot整合RocketMQ

文章目录 1、整合2、消息的生产3、消费4、发送异步消息5、补充&#xff1a;安装RocketMQ 1、整合 首先导入起步依赖&#xff0c;RocketMQ的starter不是Spring维护的&#xff0c;这一点从starter的命名可以看出来&#xff08;不是spring-boot-starter-xxx&#xff0c;而是xxx-s…

【源码】hamcrest 源码阅读 空对象模式、模板方法模式的应用

文章目录 前言1. 类图概览2. 源码阅读2.1 抽象类 BaseMatcher2.1 接口 Description提炼模式&#xff1a;空对象模式 2. 接口 Description 与 SelfDescribing 配合使用提炼模式 模板方法 后记 前言 hamcrest &#xff0c;一个被多个测试框架依赖的包。听说 hamcrest 的源码质量…

STM32 DMA从存储器发送数据到串口

1.任务描述 &#xff08;1&#xff09;ds18b20测量环境温度存储到存储器&#xff08;数组&#xff09;中。 &#xff08;2&#xff09;开启DMA将数组中的内容&#xff0c;通过DMA发送到串口 存在问题&#xff0c;ds18b20读到的数据是正常的&#xff0c;但是串口只是发送其低…

机器学习7:pytorch的逻辑回归

一、说明 逻辑回归模型是处理分类问题的最常见机器学习模型之一。二项式逻辑回归只是逻辑回归模型的一种类型。它指的是两个变量的分类&#xff0c;其中概率用于确定二元结果&#xff0c;因此“二项式”中的“bi”。结果为真或假 — 0 或 1。 二项式逻辑回归的一个例子是预测人…

Scala第十七章节

Scala第十七章节 scala总目录 文档资料下载 章节目标 了解集合的相关概念掌握Traversable集合的用法掌握随机学生序列案例 1. 集合 1.1 概述 但凡了解过编程的人都知道程序 算法 数据结构这句话, 它是由著名的瑞士计算机科学家尼古拉斯沃斯提出来的, 而他也是1984年图灵…

车险计算器微信小程序源码 带流量主功能

车险计算器微信小程序源码带流量主功能&#xff0c;可以精准的算出车险的书目&#xff0c;是一个非常实用的微信小程序源码。 简单的计算让你得知车险价值 另外也支持流量主&#xff0c;具体小编也就不多说了&#xff0c;大家自己搭建研究吧。 源码下载&#xff1a;https://d…

React xlsx(工具库) 处理表头合并

前端导出excel表格 引入xlsx插件&#xff0c;不然应该是运行不起来的 npm i xlsx xlsx中文文档 插件2 exceljs npm i exceljs exceljs中文文档 导出 例子 import { ExportExcel } from ./exportExcel/index;const columns[{title: id,dataIndex: item1,},{title: 序号,dataInd…

开环模块化多电平换流器仿真(MMC)N=6(Simulink仿真)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

RabbitMQ之Fanout(扇形) Exchange解读

目录 基本介绍 适用场景 springboot代码演示 演示架构 工程概述 RabbitConfig配置类&#xff1a;创建队列及交换机并进行绑定 MessageService业务类&#xff1a;发送消息及接收消息 主启动类RabbitMq01Application&#xff1a;实现ApplicationRunner接口 基本介绍 Fa…

12.1 使用键盘鼠标监控钩子

本节将介绍如何使用Windows API中的SetWindowsHookEx和RegisterHotKey函数来实现键盘鼠标的监控。这些函数可以用来设置全局钩子&#xff0c;通过对特定热键挂钩实现监控的效果&#xff0c;两者的区别在于SetWindowsHookEx函数可以对所有线程进行监控&#xff0c;包括其他进程中…

Spring Cloud Gateway2之路由详解

Spring Cloud Gateway路由 文章目录 1. 前言2. Gateway路由的基本概念3. 三种路由1. 静态路由2. 动态路由1. 利用外部存储2. API动态路由 3. 服务发现路由(自动路由)3.1. 配置方式3.2 自动路由&#xff08;服务发现&#xff09;原理核心源码GatewayDiscoveryClientAutoConfigur…

机器学习算法基础--KNN分类算法

文章目录 1.KNN算法原理介绍2.KNN分类决策原则3.KNN度量距离介绍3.1.闵可夫斯基距离3.2.曼哈顿距离3.3.欧式距离 4.KNN分类算法实现5.KNN分类算法效果6.参考文章与致谢 1.KNN算法原理介绍 KNN&#xff08;K-Nearest Neighbor&#xff09;工作原理&#xff1a; 在一个存在标签的…

Springcloud支付模块

客户端消费者80 order&#xff08;订单模块&#xff09; 微服务提供者8001 payment&#xff08;支付模块&#xff09; 订单模块可以调动支付模块 步骤&#xff1a; 1、建moudle 2、改写pom 3、写yml 4、主启类 5、业务类 1、建父工程&#xff08;创建spri…

架构师选择题--计算机网络

架构师选择题--计算机网络 22年考题21年考题20年考题19年真题2017考题 22年考题 d http:80 https:httpssl &#xff1a;443 b b pop3是邮件接收协议&#xff1a;110 SMTP是邮件发送协议&#xff1a;25 http:80 A 网络隔离&#xff1a;防火墙&#xff08;逻辑&#xff09;&…

C++(反向迭代器)

前言&#xff1a; 上一章我们介绍了适配器&#xff0c;也提了一下迭代器适配器&#xff0c;今天我们就从反向迭代器把迭代器适配器给解释一下。 既然 都叫迭代器容器了 就说名只要接口合适他可以封装实现各种容器需求包括vector list 。 目录 1.反向迭代器设计 1.1反向迭代…

Spring面试题学习: 单例Bean是单例模式吗?

单例Bean是单例模式吗 学习背景答案扩展知识单例模式Spring BeanJava Bean单例Bean 个人评价我的回答 学习背景 想换工作. 学习记录, 算是一个输出. 答案 通常来说, 单例模式是指在一个JVM中, 一个类只能构造出一个对象. 有很多方法来实现单例模式, 比如饿汉模式. 但是我们通…