FlatBuffers使用简介

2023-11-08

@[tools|flatbuffers|opensource]

概述###

Google在今年6月份发布了跨平台序列化工具FlatBuffers,提供了C++/Java/Go/C#接口支持,这是一个注重性能和资源使用的序列化类库。相较于Protocol Buffers,其更适用于移动设备,FlatBuffers提供更高的性能以及更低的资源需求。

特点####
  • 不需要打包/解包。它的结构化数据都以二进制形式保存,不需要数据解析过程,数据也可以方便传递
  • 省内存、性能好
  • 强类型系统,在编译阶段就能预防一些bug的产生
  • 跨平台(C++11/Java/Go/C#)
FlatBuffers和Protocol Buffers以及Json的比较:####
  • FlatBuffers的功能和Protocol Buffers很像,他们的最大不同点是在使用具体的数据之前,FlatBuffers不需要解析/解包的过程。同时,在工程中使用时,FlatBuffers的引用比Protocol Buffers方便很多,只需要包含两三个头文件即可
  • JSON作为数据交换格式,被广泛用户各种动态语言之间(当然也包括静态语言)。它的优点是易于理解(可读性好),同时它的最大的缺点那就是解析时的性能问题了。而且因为它的动态类型特点,你的代码可能还需要多写好多类型、数据检查逻辑。
FlatBuffers的使用步骤####
  • 编写一个用来定义数据结构的schema(IDL,接口定义)文件,如下所示:
    //flatbuffers test struct

    namespace Jason.Flat.Test;

    enum Color : byte { Red = 1, Green, Blue }

    union Any { TextureData, Texture }

    table TestAppend {  test_num:int;  test_num2:int; } table TextureData {  image_size:int (id:0);  image_data:[ubyte] (id:1);  image_test:short(id:3);  test_num2:int(id:2); } table Texture {  num_textures:short;  textures:[TextureData];  num_test:short = 30;  num_test1:short (deprecated);  num_test2:short;  test_append:TestAppend; } root_type Texture; 

将上述代码保存为TestFlat.fbs文件之后,即可用flatc来编译了

  • 使用FlatBuffer编译器flatc生成数据结构源代码(C++头文件或者Java类)
    登录GitHub,下载所需版本的源码及工程文件,在build目录下有VS2010的工程文件(当然,你也可以选择利用CMake自己本地创建工程),打开配置好flatc工程的传入参数,如下:
    -c -o ./ ./TestFlat.fbs
    运行flatc工程,即可在当前工程目录下生成TestFlat_generated.h头文件,这个头文件中包含了我们所需的所有结构体、枚举类型等以及相应的存取方法和验证方法
  1. 使用FlatBufferBuilder类创建flat的二进制buffer
    以下代码展示了如何利用FlatBufferBuilder创建相应buffer:
    //read serialized buffer
    flatbuffers::FlatBufferBuilder builder_data;

    int test_append = 300;
    auto name_test = builder_data.CreateString("TestAppend"); auto testApp = CreateTestAppend(builder_data, test_append, test_append); int image_size = 12; unsigned char inv_data[] = { 11, 2, 4, 2, 10, 3, 5 ,7, 10, 39, 45, 23 }; auto name = builder_data.CreateString("TextureData"); auto image_data = builder_data.CreateVector(inv_data, image_size); int image_test = 900; auto texture_data = CreateTextureData(builder_data, image_size, image_data, image_test, image_test); //flatbuffers::FlatBufferBuilder builder_tex; int texture_num = 1; auto name_tex = builder_data.CreateString("Texture"); vector<flatbuffers::Offset<TextureData>> tex_vec; tex_vec.push_back(texture_data); auto tex_data = builder_data.CreateVector(tex_vec); int num_text = 100, num_text2 = 200, num_text3 = 300; auto texture = CreateTexture(builder_data, texture_num, tex_data, num_text, num_text2, testApp); builder_data.Finish(texture); 

要使上述正确运行,除了引用C++基本库之外,需在文件头部添加以下代码:

#include "flatbuffers/flatbuffers.h"
#include "idl.h" #include "util.h" #include "TestFlat_generated.h" using namespace Jason::Flat::Test; 

上述代码的编写中规中矩,其中CreateString和CreateVector都是FlatBufferBuilder类的成员函数,分别用于创建适用于FlatBuffer内存结构的字符串数据以及向量数据。其余的方法,如CreateTextureData、CreateTexture均是由flatc根据IDL文件(TestFlat.fbs)自动生成的头文件中用于创建相应结构体的函数。最后一句builder_data.Finish(texture)用于优化对齐写入builder_data的内存结构。

  1. 保存buffer到本地或者直接通过网络发送
    保存buffer到本地的代码,如下:
std::cout << builder_data.GetSize() << std::endl; flatbuffers::SaveFile("texture.bin", reinterpret_cast<char *>(builder_data.GetBufferPointer()), builder_data.GetSize(), true); 

将数据保存到名为texture.bin的二进制文件中,其中通过builder_data.GetBufferPointer()获取内存指针,builder_data.GetSize()获取内存大小,最后一个参数用于制定是否生成二进制文件。

  1. 接收并buffer并读取数据内容
    读取二进制文件的代码如下:
    string binaryfile;
    bool ok = flatbuffers::LoadFile("texture.bin", false, &binaryfile);

    flatbuffers::Verifier tex_verify(builderOut.GetBufferPointer(), builderOut.GetSize());
    bool verify_flag = VerifyTextureBuffer(tex_verify);

    flatbuffers::FlatBufferBuilder builderOut;
    TextureBuilder* texBuilder = new TextureBuilder(builderOut); builderOut.PushBytes(reinterpret_cast<unsigned char*>(const_cast<char *>(binaryfile.c_str())), binaryfile.size()); std::cout << builderOut.GetSize() << std::endl; auto model = GetTexture(builderOut.GetBufferPointer()); int outNum = model->num_textures(); const flatbuffers::Vector<flatbuffers::Offset<TextureData>>* outTex = model->textures(); TextureData* outTexData = (TextureData *)outTex->Get(0); int outSize = outTexData->image_size(); const flatbuffers::Vector<unsigned char>* outData = outTexData->image_data(); int x = outData->Get(5); int len = outData->Length(); delete texBuilder; 

上述代码中VerifyTextureBuffer用于验证读取的内存是否为FlatBuffers的内存块,是则返回true,不是则返回false。通过GetTexture获取指针之后,结构体中的变量均可以通过相应方法(各方法名请查看自动生成的头文件)获取。

总结####

利用FlatBuffers来进行数据保存及传输的优点显而易见,它利用自身特殊的编码格式,能一定程度上减少内存的占用,优化读取的性能。更重要的是,对于数据结构的向前向后兼容提供了很好的扩展性,方便又高效:

  • 要想让数据结构具有可扩展性,需将数据结构定义为table,它是数据扩展的基础,FlatBuffers中的struct类型不支持扩展
  • 如果想在后续的版本中删除数据结构中的某些字段,只要在将要删除的字段后面添加(deprecated)即可,当然需要保证删除的字段在之前版本的程序中不会引起程序崩溃(该删掉的字段在上一版本的程序中获取到的会是个空指针或空值,只需保证程序在获取到空值或空指针之后不会出现异常即可)
  • 如果想在后续版本中向数据结构中添加某些字段,需添加到table中最后一个字段的后面,若是想table中随意位置添加字段,需如上面TextureData 的定义,给每个字段指明添加id:n(n从0开始)

目前FlatBuffers还不是很完善,碰到问题可以到FlatBuffers Issues Tracker去提交或则寻找答案。

参考链接
FlatBuffers Documentation
github repository
Google FlatBuffers 跨平台序列化工具
FlatBuffers与protobuf性能比较



作者:drybeans
链接:https://www.jianshu.com/p/6eb04a149cd8
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FlatBuffers使用简介 的相关文章

  • Java中ArrayList的交集和并集

    有什么方法可以做到这一点吗 我正在寻找 但没有找到 另一个问题 我需要这些方法 以便我可以过滤文件 有些是AND过滤器 有些是OR过滤器 就像集合论中的那样 所以我需要根据所有文件和保存这些文件的联合 相交 ArrayList 进行过滤 我
  • 如何通过 javaconfig 使用 SchedulerFactoryBean.schedulerContextAsMap

    我使用 Spring 4 0 并将项目从 xml 移至 java config 除了访问 Service scheduleService 带注释的类来自QuartzJobBean executeInternal 我必须让它工作的 xml 位
  • 使用 LinkedList 实现下一个和上一个按钮

    这可能是一个愚蠢的问题 但我很难思考清楚 我编写了一个使用 LinkedList 来移动加载的 MIDI 乐器的方法 我想制作一个下一个和一个上一个按钮 以便每次单击该按钮时都会遍历 LinkedList 如果我硬编码itr next or
  • 如何在 Spring 中禁用使用 @Component 注释创建 bean?

    我的项目中有一些用于重构逻辑的通用接口 它看起来大约是这样的 public interface RefactorAwareEntryPoint default boolean doRefactor if EventLogService wa
  • 如何获取之前的URL?

    我需要调用我的网络应用程序的 URL 例如 如果有一个从 stackoverflow com 到我的网站 foo com 的链接 我需要 Web 应用程序 托管 bean 中的 stackoverflow 链接 感谢所有帮助 谢谢 并不总是
  • 在接口中使用默认方法是否违反接口隔离原则?

    我正在学习 SOLID 原则 ISP 指出 客户端不应被迫依赖于他们所使用的接口 不使用 在接口中使用默认方法是否违反了这个原则 我见过类似的问题 但我在这里发布了一个示例 以便更清楚地了解我的示例是否违反了 ISP 假设我有这个例子 pu
  • 没有 Spring 的自定义 Prometheus 指标

    我需要为 Web 应用程序提供自定义指标 问题是我不能使用 Spring 但我必须使用 jax rs 端点 要求非常简单 想象一下 您有一个包含键值对的映射 其中键是指标名称 值是一个简单的整数 它是一个计数器 代码会是这样的 public
  • 将 MOXy 设置为 JAXB 提供程序,而在同一包中没有属性文件

    我正在尝试使用 MOXy 作为我的 JAXB 提供程序 以便将内容编组 解组到 XML JSON 中 我创建了 jaxb properties 文件 内容如下 javax xml bind context factory org eclip
  • 像 Java 这样的静态类型语言中动态方法解析背后的原因是什么

    我对 Java 中引用变量的动态 静态类型和动态方法解析的概念有点困惑 考虑 public class Types Override public boolean equals Object obj System out println i
  • 如何在用户输入数据后重新运行java代码

    嘿 我有一个基本的java 应用程序 显示人们是成年人还是青少年等 我从java开始 在用户输入年龄和字符串后我找不到如何制作它它们被归类为 我希望它重新运行整个过程 以便其他人可以尝试 的节目 我一直在考虑做一个循环 但这对我来说没有用
  • Java ResultSet 如何检查是否有结果

    结果集 http java sun com j2se 1 4 2 docs api java sql ResultSet html没有 hasNext 方法 我想检查 resultSet 是否有任何值 这是正确的方法吗 if resultS
  • tomcat 中受密码保护的应用程序

    我正在使用 JSP Servlet 开发一个Web应用程序 并且我使用了Tomcat 7 0 33 as a web container 所以我的要求是tomcat中的每个应用程序都会password像受保护的manager applica
  • 在我的 Spring Boot 示例中无法打开版本 3 中的 Swagger UI

    我在 Spring Boot 示例中打开 swagger ui 时遇到问题 当我访问 localhost 8080 swagger ui 或 localhost 8080 root api name swagger ui 时出现这种错误 S
  • Java 和 Python 可以在同一个应用程序中共存吗?

    我需要一个 Java 实例直接从 Python 实例数据存储中获取数据 我不知道这是否可能 数据存储是否透明 唯一 或者每个实例 如果它们确实可以共存 都有其单独的数据存储 总结一下 Java 应用程序如何从 Python 应用程序的数据存
  • 最新的 Hibernate 和 Derby:无法建立 JDBC 连接

    我正在尝试创建一个使用 Hibernate 连接到 Derby 数据库的准系统项目 我正在使用 Hibernate 和 Derby 的最新版本 但我得到的是通用的Unable to make JDBC Connection error 这是
  • 如何使用mockito模拟构建器

    我有一个建造者 class Builder private String name private String address public Builder setName String name this name name retur
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java
  • 使用反射覆盖最终静态字段是否有限制?

    在我的一些单元测试中 我在最终静态字段上的反射中遇到了奇怪的行为 下面是说明我的问题的示例 我有一个基本的 Singleton 类 其中包含一个 Integer public class BasicHolder private static
  • 双枢轴快速排序和快速排序有什么区别?

    我以前从未见过双枢轴快速排序 是快速排序的升级版吗 双枢轴快速排序和快速排序有什么区别 我在 Java 文档中找到了这个 排序算法是双枢轴快速排序 作者 弗拉基米尔 雅罗斯拉夫斯基 乔恩 本特利和约书亚 布洛赫 这个算法 在许多数据集上提供
  • Spring Rest 和 Jsonp

    我正在尝试让我的 Spring Rest 控制器返回jsonp但我没有快乐 如果我想返回 json 但我有返回的要求 完全相同的代码可以正常工作jsonp我添加了一个转换器 我在网上找到了用于执行 jsonp 转换的源代码 我正在使用 Sp

随机推荐

  • 测试工程师面试之设计测试用例

    以下的问题答案 仅供参考 如小伙伴们有更好的答案 欢迎大家评论区留言 谢谢大家 测试工程师面试之设计测试用例 1 请说一说简单用户界面登陆过程都需要做哪些分析 2 请对此系统设计测试用例 一个系统 多个摄像头 抓拍车牌 识别车牌 上传网上
  • 【基于Proteus 8 Professional和Keil uVision5简单共阴极数码管点亮】

    1 前面的一些Keil uVision5环境搭建具体的操作我已经省略 可以参照我前面写的博客 2 Main c代码 include stm32f10x h uint16 t table 0x3f 0x06 0x5b 0x4f 0x66 0x
  • 模拟电路设计(13)--- 振荡器电路原理简介

    概述 所谓振荡器电路就是一种在没有外界输入信号的情况下能自行产生周期性交变信号输出的电子电路 可以作为信号源 定时源 能量变换电路 频谱变换电路等等 普遍应用于通信电子系统 振荡器的种类很多 按原理分 反馈振荡器和负阻振荡器 按输出频率分
  • JavaBean转有序的Json字符串

    前言 随着国密算法普及 接口json加签传输对字段顺序有要求 处理代码 public static void main String args throws IllegalAccessException User user new User
  • chatgpt配合xmind制作思维导图

    原理 xmind支持将markdown文件转化成思维导图的形式 提示词 我将提供以下文章 请帮我使用Xmind工具创建一个 的思维导图 其中包含多个主题和子主题 以及叶子节点 请你提供一些Markdown格式的文本 以便与Xmind兼容 在
  • Oracle监控的关键指标(一)

    先收集一些Oracle的关键指标 最近有空的话再考虑将一些比较有代表性的监控点进行指标化 指标化的数据在通过python脚本对进行性能上监控 最终部署在目前维护的oracle数据库上 0 找使用CPU多的用户session select a
  • WSL安装教程

    wsl安装教程 引言 前期准备工作 安装wsl 第一步 第二步 检测系统版本 第三步 确定虚拟机特性 第四步 下载Linux内核的更新包 第五步 设置WSL 2作为默认版本 第六步 选择Linux发行版本并设置Linux账号 小TIPS 引
  • CocoaPods导入第三方库,提示找不到头文件的解决方法

    最近一直在了解MVVM架构模式 也知道了ReactiveCocoa框架对MVVM实现的便利与优雅 但是CocoaPods导入ReactiveCocoa框架后 却出现一个问题 就是引入头文件的时候说找不到头文件 如下图 解决方法如下 1 找到
  • Fragment详解

    Fragment有自己的生命周期 Fragment依赖于Activity Fragment通过getActivity 可以获取所在的Activity Activity通过FragmentManager的findFragmentById 或f
  • QT5.15以及QT VS TOOL安装教程

    QT5 15以及QT VS TOOL安装教程 1 QT5 15下载安装教程 点击这个链接 https download qt io 在official release online installers目录下选择exe文件下载windows
  • vue重新进页面重新加载mounted或者created中的内容

    vue的项目中 如果再次进入当前页面需要重新加载mounted方法可以使用 activated 这个方法内就可以执行需要进入页面重新加载的方法来替代mounted或者created方法 这样就可以满足不重新加载页面就可以直接将方法重新执行一
  • 打印机错误0x00000bc4的解决办法

    共享打印机在使用过程中难免会出现一些问题 比如连接共享打印机错误 提示代码0x00000bc4 这该如何解决 共享打印机出现问题是件非常麻烦的事 下面就来看看小编整理的解决办法吧 Win11连接共享打印机错误0x00000bc4解决方法 1
  • RabbitMQ:work结构

    gt 只需要在消费者端 添加Qos能力以及更改为手动ack即可让消费者 根据自己的能力去消费指定的消息 而不是默认情况下由RabbitMQ平均分配了 生产者不变 正常发布消息到默认的exchange gt 消费者指定Qoa和手动ack 生产
  • 2023Web前端面试题及答案(一)

    答案仅供参考 每人的理解不一样 文章目录 1 简单说一说事件流原理 事件流 1 事件流是指页面 接收事件的顺序 2 假设页面中的元素都具备相同的事件 并且这些个元素之间是相互嵌套的 关系 3 那么在触发一个元素的事件时候 会触发其他的元素
  • 华为od机考真题-HJ105-记负均正II(较难)

    非负数缓存 data lst 负数个数 count 0 while 1 try data int input if data gt 0 data lst append
  • 卷积核大小不一样的卷积

    这种不是33而是51的 参考这个https blog csdn net qq 37541097 article details 102926037 也就是说把中间写成 3 5 就可以了
  • Open3D:Win10 + VS2017配置Open3D(C++、python)

    累了就要打游戏 2020 08 25 15 13 10 3350 收藏 25 分类专栏 Open3D 文章标签 点云 Open3D C 版权 Open3D 专栏收录该内容 5 篇文章1 订阅 订阅专栏 20200825 今天七夕 呱呱呱 O
  • 苹果开发者账号申请教程

    只有苹果开发者账号才能上架App Store 苹果开发者需要年费 是苹果公司收的 公司 政府和企业账号申请比较复杂 如果不想麻烦 或没有visa银行卡 可以联系他们技术代申请 如果只是安装ios应用到自己手机测试 现在只需要注册一个普通的苹
  • CSDN自带编辑器语法

    这里写自定义目录标题 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题 有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你的列表 创建一个表格 设定内容居中 居左 居右 Sma
  • FlatBuffers使用简介

    tools flatbuffers opensource 概述 Google在今年6月份发布了跨平台序列化工具FlatBuffers 提供了C Java Go C 接口支持 这是一个注重性能和资源使用的序列化类库 相较于Protocol B