1.优点
2.使用方法
-
下载文件编译工具
1.下载源码
$ git clone https://github.com/google/flatbuffers
2.下载编译工具
https://cmake.org/download/ 下载对应的cmake工具参考网上:可以使用 cmake编译成flatc工具。但是暂时没有搞懂怎么编译?
最后,在这个地方可以下载windows的 exe可以运用文件。
https://github.com/google/flatbuffers/releases
比较坑的最新的1.7.1没有exe没有exe下载。也没有看后面的,以为需要自己编译。最后一不留 神看到1.7.0有下载。哎。。。。。。。。 编写描述
使用 FlatBuffers 的 IDL 定义好数据结构 Schema,编写 Schema 的详细文档在这里 http://google.github.io/flatbuffers/flatbuffers_guide_writing_schema.html。
参考一个例子
//包名
namespace com.xx.xx;
table Items {
ItemId : long;
timestemp : int;
basic:[Basic];
}
table Basic{
id:int;
name:string;
email:int;
code:long;
isVip:bool;
count:int;
carList:[Car];
}
table Car{
id:long;
number:long;
describle:string;
}
root_type Items;
- 使用工具
2.根据json生成和fbs 生成flatbuffer 二进制文件.bin
例如repos_json.json (有数据),对应的数据结构repos_schema.fbs ,生成repos_json.bin(二进制flatbuffer格式的)
$ ./flatc -j -b repos_schema.fbs repos_json.json
- 工程中使用
编写对应描述文件,翻译成对应语言的类。把对应的类, 放到你的工程中。
- 序列化于反序列化
public void serialize(View v){
//==================序列化========================
FlatBufferBuilder builder = new FlatBufferBuilder();
int id1 = builder.createString("兰博基尼");
//准备Car对象
int car1 = Car.createCar(builder,10001L,88888L,id1);
int id2 = builder.createString("奥迪A8");
//准备Car对象
int car2 = Car.createCar(builder,10001L,88888L,id2);
int id3 = builder.createString("奥迪A9");
//准备Car对象
int car3 = Car.createCar(builder,10001L,88888L,id3);
int[] cars = new int[3];
cars[0]= car1;
cars[1] = car2;
cars[2] = car3;
//创建Basic对象里面的Car集合
int carList = Basic.createCarListVector(builder,cars);
int name = builder.createString("jack");
int email = builder.createString("jack@qq.com");
int basic = Basic.createBasic(builder,10,name,email,100L,true,100,carList);
int basicOffset = Items.createBasicVector(builder,new int[]{basic});
Items.startItems(builder);
Items.addItemId(builder,1000L);
Items.addTimestemp(builder,2016);
Items.addBasic(builder,basicOffset);
int rootItems = Items.endItems(builder);
Items.finishItemsBuffer(builder,rootItems);
//============保存数据到文件=================
File sdcard = Environment.getExternalStorageDirectory();
//保存的路径
File file = new File(sdcard,"Items.txt");
if(file.exists()){
file.delete();
}
ByteBuffer data = builder.dataBuffer();
FileOutputStream out = null;
FileChannel channel = null;
try {
out = new FileOutputStream(file);
channel = out.getChannel();
while(data.hasRemaining()){
channel.write(data);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null){
out.close();
}
if(channel!=null){
channel.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//===================反序列化=============================
FileInputStream fis = null;
FileChannel readChannel = null;
try {
fis = new FileInputStream(file);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
readChannel = fis.getChannel();
int readBytes = 0;
while ((readBytes=readChannel.read(byteBuffer))!=-1){
System.out.println("读取数据个数:"+readBytes);
}
//把指针回到最初的状态,准备从byteBuffer当中读取数据
byteBuffer.flip();
//解析出二进制为Items对象。
Items items = Items.getRootAsItems(byteBuffer);
//读取数据测试看看是否跟保存的一致
Log.i(TAG,"items.id:"+items.ItemId());
Log.i(TAG,"items.timestemp:"+items.timestemp());
Basic basic2 = items.basic(0);
Log.i(TAG,"basic2.name:"+basic2.name());
Log.i(TAG,"basic2.email:"+basic2.email());
//carList
int length = basic2.carListLength();
for (int i=0;i<length; i++){
Car car = basic2.carList(i);
Log.i(TAG,"car.number:"+car.number());
Log.i(TAG,"car.describle:"+car.describle());
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(readChannel!=null){
readChannel.close();
}
if(fis!=null){
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.基本原理
FlatBuffers 保存在一个 byte 数组中,有一个“支点”指针(pivot point)以此为界,存储的内容分为两个部分:元数据和数据内容。其中元数据部分就是数据在前面,其长度等于对象中的字段数量,每个 byte 保存对应字段内容在数组中的索引(从支点位置开始计算)。
namespace com.race604.fbs;
enum FriendshipStatus: int {Friend = 1, NotFriend}
table Person {
name: string;
friendshipStatus: FriendshipStatus = Friend;
spouse: Person;
friends: [Person];
}
root_type Person;
上面的 Person 对象第一个字段是 name,其值的索引位置是 1,所以从索引位置 1 开始的字符串,就是 name 字段的值 "John"。第二个字段是 friendshipStatus,其索引值是 6,找到值为 2, 表示 NotFriend。第三个字段是 spouse,也一个 Person 对象,索引值是 12,指向的是此对象的支点位置。第四个字段是一个数组,图中表示的数组为空,所以索引值是 0。