c++对象的序列化与反序列化的解决方案----flatbuffers的使用

摘要:
简介一、什么是FlatBuffers?注:1、flatbuffers的类型有很多我就没有一一列举了,大家可以在flatbuffers的文档里看到。如果没有Layer中没有std::vectortranform,那么这里我们的Point的定义可以是structPoint_Fb,因为我没有找到flatbuffers里面如何使用结构体数组的方法。我们就是要创建一个layer_Fb的对象,这个就是Layer对象对应的flatbuffers的对象,他包含了Layer对象的所有的信息。

概述

本篇blog主要是给大家介绍FlatBuffers的相关的信息和用法,当我在了解的FlatBuffers时,国内还没有一些相关的文章去介绍FlatBuffers,不得不FQ去google相关的用法,然后理解并应用到自己的代码中,学习的时间成本很高。所以就花了点时间整理一份具体的用法,提供给大家一个参考。

简介

一、什么是FlatBuffers?

FlatBuffers是一个开源的、跨平台的、高效的、提供了C++/Java接口的序列化工具库。它是Google专门为游戏开发或其他性能敏感的应用程序需求而创建。尤其更适用于移动平台,这些平台上内存大小及带宽相比桌面系统都是受限的,而应用程序比如游戏又有更高的性能要求。它将序列化数据存储在缓存中,这些数据既可以存储在文件中,又可以通过网络原样传输,而不需要任何解析开销。

代码托管主页:https://github.com/google/flatbuffers

项目介绍主页:http://google.github.io/flatbuffers/index.html

二、FlatBuffers用途有哪些?

1、对C++代码的序列化与反序列化:①写本地缓存,方便读取。②用于网络数据发送。

2、将xml、json文件转换成二进制文件,大大缩减加载文件时间

用法

关于FlatBuffers的用法,我下面还是通过代码向大家讲解,这样更直观,更容易理解。

classPoint
{
    floatx;
    floaty;
};

classNode
{

   std::stringname;
   Point position;
};

classLayer
: publicNode
{
   Node*friend;
   std::vector<Node*>children;
   std::vector<Point *>transform;
};

1、使用前的准备

首先构建一个schema文件。schema文件主要是记录了我们所要用的对象的成员信息。

//>>>>>>>>> schema begin <<<<<<<<<<<
namespace Layer; table Point_Fb { x:float;
y:float;
} table Node_Fb { name:string;
position:Point_Fb; }
table Layer_Fb
{
super:Node_Fb;
friend:Node_Fb;
children:[Node_Fb];
transform:[Point_Fb];
} root_type Layer_Fb;
//>>>>>>>>> schema end <<<<<<<<<<<
到这里我们的schema文件已经写完了,然后保存为
Layer_Fb.fbs文件。
然后下载google的flatbuffers的开源代码编译flatc.cpp得到flatc可执行文件,然后运行
flatc -c -o ./ ./Layer_Fb.fbs 生成一个Layer_Fb_generated.h的头文件,加到项目中。到这里,我们的准备工作就做完了。

注:

1、flatbuffers的类型有很多我就没有一一列举了,大家可以在flatbuffers的文档里看到。
2、schema文件中的除了table还有struct。区别就在于able是Flatbuffers中用来定义对象的主要方式,和struct最大的区别在于:它的每个字段都是可选的,而struct的所有成员都是required。
table除了成员名称和类型之外,还可以给成员一个默认值,如果不显式指定,则默认为0(或空)。struct不能定义scalar成员,比如说string类型的成员。在生成C++代码时,struct的成员顺序
会保持和IDL的定义顺序一致,如果有必要对齐,生成器会自动生成用于对齐的额外成员。
如果没有Layer中没有std::vector<Point*> tranform,那么这里我们的Point的定义可以是struct Point_Fb,因为我没有找到flatbuffers里面如何使用结构体数组的方法。(如果各位有找到还望不吝赐教)

2、具体使用方法

1、序列化

这里我有个对象就是auto layer = new Layer();如何序列化呢?

我们就是要创建一个layer_Fb的对象,这个就是Layer对象对应的flatbuffers的对象,他包含了Layer对象的所有的信息。

#include "Layer_Fb_generated.h"flatbuffers::FlatBufferBuilder builder_data;
    auto position_fb =CreatePoint_Fb(builder_data,layer.position.x,layer.position.y);
    auto super_fb = CreateNode_Fb(builder_data,builder_data.CreateString(layer.name),&position_fb);
    auto friend_fb =...;
    
    std::vector<flatbuffers::Offset<Node_Fb>>Node_fbList;
    for(auto child : layer.children)
    {
        auto position_fb =CreatePoint_Fb(builder_data,child.position.x,child.position.y);
        auto child_fb = CreateNode_Fb(builder_data,builder_data.CreateString(child.name),&position_fb);
        Node_fbList.push_back(child_fb);
    }
    
    std::vector<flatbuffers::Offset<Point_Fb>>transformList;
    for(auto point : layer.transform)
    {
        auto position_fb =CreatePoint_Fb(builder_data,layer.position.x,position.y);
        transformList.push_back(position_fb);
    }
    
    auto layer_fb =CreateLayer_Fb(builder_data,position_fb,super_fb,friend_fb,Node_fbList,transformList);
//auto layer_fb = CreateLayer_Fb(builder_data,
//position_fb,
//super_fb,
//friend_fb,
//Node_fbList.size() == 0 ? 0 : Node_fbList, //这样可以减少多余存储空间
//transformList);
builder_data.Finish(texture);
    
//(char *)builder_data.GetBufferPointer(), builder_data.GetSize() 取得转换后的二进制文件。保存到本地或者用于网络传输

2、反序列化

auto layer_fb = flatbuffers::GetRoot<Layer_Fb>(builder_data.GetBufferPointer());//
    layer_fb->super/*schema 中的对象的名字*/();
    layer_fb->friend();
    layer_fb->children();
    layer_fb->transfrom();
  创建layer对象,对其一个个赋值就可以了。
注:
这里并不是只能对schame中的root_type才能序列化,例如:你想只对Node_fb进行序列化,你就可以在得到node_fb对象的时候直接builder.finish(node_fb),返回利用
  flatbuffers::GetRoot<Node_Fb/*类型不要错咯*/>(builder_data.GetBufferPointer());方法一样可以

3、扩展

那么如何对xml、json文件进行序列化呢?

我的做法就是把xml、json文件解析成c++对象,然后序列化,保存到本地。然后就用保存的文件进行读取、反序列化操作。我对比过两中方式的读取效率。很明显读取flatbuffers文件后进行反序列化要比xml、json速度快6~10倍!但看这个值可能没感觉,当你解析一个xml可能用0.01s,但是解析flatbuffers文件你只要0.003秒。文件一多对比就会出来了。尤其是在手机游戏上的时候,启动和界面切换加载就会明显快好多。(如果你从事cocos2dx开发的话,你可以研究研究cocos的csb文件,其实就是一个flatbuffers文件。)    

谢谢各位的阅读!

各位有什么疑问可以直接在我的blog下留言或者是发送的我的个人邮箱relvin@qq.com。

免责声明:文章转载自《c++对象的序列化与反序列化的解决方案----flatbuffers的使用》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇拜耳阵列(Bayer Pattern)简介Nginx – access_log格式及配置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Fastjson远程代码执行漏洞复现

fastjson漏洞简介 Fastjson是一个Java库,可用于将Java对象转换为其JSON表示形式。它还可以用于将JSON字符串转换为等效的Java对象,fastjson爆出多个反序列化远程命令执行漏洞,攻击者可以通过此漏洞远程执行恶意代码来入侵服务器。 fastjson漏洞原理 先来分析fastjson 1.2.47的POC { "a":...

sqlserver 中含有某字符串

查找 sqlserver 中字符串的ascii码SET TEXTSIZE 0-- Create variables for the character string and for the current -- position in the string.DECLARE @position int, @string char(8)-- Initializ...

Java审计之CMS中的那些反序列化漏洞

Java审计之CMS中的那些反序列化漏洞 0x00 前言 过年这段时间比较无聊,找了一套源码审计了一下,发现几个有意思的点拿出来给分享一下。 0x01 XStream 反序列化漏洞 下载源码下来发现并不是源代码,而是一个的文件夹,里面都已经是编译过的一个个class文件。 在一个微信回调的路由位置里面找到通过搜索类名 Serialize关键字找到了一个工具...

Json.Net序列化和反序列化设置

首先补充一点,Json.Net是支持序列化和反序列化DataTable,DataSet,Entity Framework和NHibernate的.我举例说明DataTable的序列化和反序列化.创建一个DataTable对象,如下: DataTable dt = newDataTable(); DataCol...

Netty 系列之 Netty 高性能之道

http://www.infoq.com/cn/articles/netty-high-performance 1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用。相比于传统基于Java序列化+BIO(同步阻...

零拷贝(Zero-copy)及其应用详解

传统的数据传输方法在互联网时代,从某台机器将一份数据(比如一个文件)通过网络传输到另外一台机器,是再平常不过的事情了。如果按照一般的思路,用Java语言来描述发送端的逻辑,大致如下: Socket socket = new Socket(HOST, PORT); InputStream inputStream = new FileInputStream(F...