转载自:https://www.jianshu.com/p/6eb04a149cd8
重要补充:https://www.cnblogs.com/lizhenghn/p/3854244.html
https://www.coder4.com/archives/4386?utm_source=tuicool&utm_medium=referral
java型序列化反序列化:https://www.jianshu.com/p/8df23cd182ec
Google在今年6月份发布了跨平台序列化工具FlatBuffers,提供了C++/Java/Go/C#接口支持,这是一个注重性能和资源使用的序列化类库。相较于Protocol Buffers,其更适用于移动设备,FlatBuffers提供更高的性能以及更低的资源需求。
//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
来编译了
-c -o ./ ./TestFlat.fbs
//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的内存结构。
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()
获取内存大小,最后一个参数用于制定是否生成二进制文件。
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来进行数据保存及传输的优点显而易见,它利用自身特殊的编码格式,能一定程度上减少内存的占用,优化读取的性能。更重要的是,对于数据结构的向前向后兼容提供了很好的扩展性,方便又高效:
目前FlatBuffers还不是很完善,碰到问题可以到FlatBuffers Issues Tracker去提交或则寻找答案。
参考链接
FlatBuffers Documentation
github repository
Google FlatBuffers 跨平台序列化工具
FlatBuffers与protobuf性能比较