flatbuffer介绍和用法
介紹
flatbuffer是google發(fā)布的一個跨平臺序列化框架具有如下特點
1、對序列化的數(shù)據(jù)不需要打包和拆包
2、內(nèi)存和效率速度高,擴展靈活
3、代碼依賴較少
4、強類型設(shè)計,編譯期即可完成類型檢查
5、使用簡單、可跨平臺使用
安裝
git clone git@github.com:google/flatbuffers.git
cd flatbuffers
brew install cmake
cmake -G "Unix Makefiles"
make
make install
flatc --version
編寫flatbuffer文件
// Example IDL file for our monster's schema.
namespace com.frank.learning;
enum Color:byte { Red = 0, Green, Blue = 2 }
union Equipment { Weapon } // Optionally add more tables.
struct Vec3 {
x:float;
y:float;
z:float;
}
table Monster {
pos:Vec3; // Struct.
mana:short = 150;
hp:short = 100;
name:string;
friendly:bool = false (deprecated);
inventory:[ubyte]; // Vector of scalars.
color:Color = Blue; // Enum.
weapons:[Weapon]; // Vector of tables.
equipped:Equipment; // Union.
}
table Weapon {
name:string;
damage:short;
}
root_type Monster;
將文件保存為monster.fbs,下面進行編譯
flatc --java monster.fbs
執(zhí)行完后會在當前目錄下生成Java文件
IntelliJ測試flatbuffer
將生成的Java代碼拷到項目中,新建SampleBinary類
package com.frank.learning;
import com.google.flatbuffers.FlatBufferBuilder;
import java.nio.ByteBuffer;
public class SampleBinary {
public static void main(String[] args){
//使用FlatBufferBuilder 完成對象序列化
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
//返回該String的偏移地址
int weaponOneName = builder.createString("Sword");
short weaponOneDamage = 3;
int weaponTwoName = builder.createString("Axe");
short weaponTwoDamage = 5;
// 使用createWeapon創(chuàng)建Weapon對象,并返回該對象的偏移地址
int sword = Weapon.createWeapon(builder, weaponOneName, weaponOneDamage);
int axe = Weapon.createWeapon(builder, weaponTwoName, weaponTwoDamage);
// Serialize a name for our monster, called "Orc".
int name = builder.createString("Orc");
// 創(chuàng)建一個Vector對象,并且返回它的偏移地址
byte[] treasure = {0, 1, 13, 12, 4, 5, 6, 7, 8, 9};
int inv = Monster.createInventoryVector(builder, treasure);
// Place the two weapons into an array, and pass it to the `createWeaponsVector()` method to
// create a FlatBuffer vector.
int[] weaps = new int[2];
weaps[0] = sword;
weaps[1] = axe;
// Pass the `weaps` array into the `createWeaponsVector()` method to create a FlatBuffer vector.
int weapons = Monster.createWeaponsVector(builder, weaps);
// startMonster聲明開始創(chuàng)建Monster對象,使用endMonster聲明完成Monster對象
Monster.startMonster(builder);
Monster.addPos(builder, Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f));
Monster.addName(builder, name);
Monster.addColor(builder, Color.Red);
Monster.addHp(builder, (short)300);
Monster.addInventory(builder, inv);
Monster.addWeapons(builder, weapons);
Monster.addEquippedType(builder, Equipment.Weapon);
Monster.addEquipped(builder, axe);
int orc = Monster.endMonster(builder);
// 調(diào)用finish方法完成Monster對象
builder.finish(orc); // You could also call `Monster.finishMonsterBuffer(builder, orc);`.
// 生成二進制文件
byte[] buf = builder.sizedByteArray();
// 至此完成對象數(shù)據(jù)序列化
//模擬從獲取到二進制數(shù)據(jù) 進行反序列化對象
ByteBuffer buffer = ByteBuffer.wrap(buf);
//根據(jù)該二進制數(shù)據(jù)列生成Monster對象
Monster monster = Monster.getRootAsMonster(buffer);
short hp = monster.hp();
System.out.println(hp);
short mana = monster.mana();
System.out.println(mana);
String resultName = monster.name();
System.out.println(resultName);
Vec3 pos = monster.pos();
float x = pos.x();
float y = pos.y();
float z = pos.z();
System.out.println("X: "+x+" Y: "+y+" Z: "+z);
int invLength = monster.inventoryLength();
int thirdItem = monster.inventory(2);
System.out.println(thirdItem);
int weaponsLength = monster.weaponsLength();
String secondWeaponName = monster.weapons(1).name();
short secondWeaponDamage = monster.weapons(1).damage();
System.out.println("weaponsLength: "+weaponsLength+" secondWeaponName: "+secondWeaponName+" secondWeaponDamage: "+secondWeaponDamage);
int unionType = monster.equippedType();
if (unionType == Equipment.Weapon) {
Weapon weapon = (Weapon)monster.equipped(new Weapon()); // Requires explicit cast
// to `Weapon`.
String weaponName = weapon.name(); // "Axe"
short weaponDamage = weapon.damage(); // 5
System.out.println("weaponName: "+weaponName+" weaponDamage: "+weaponDamage);
}
}
}
pom文件加入flatbuffer相關(guān)jar包
<dependency>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId>
<version>1.12.0</version>
</dependency>
輸出結(jié)果如下
300 150 Orc X: 1.0 Y: 2.0 Z: 3.0 13 weaponsLength: 2 secondWeaponName: Axe secondWeaponDamage: 5 weaponName: Axe weaponDamage: 5
flatbuffer原理
flatbuffer將數(shù)據(jù)存在一個一維數(shù)組當中,緩存在一個bytebuffer當中。一個flatbuffer對象在數(shù)組中被分為兩部分,元數(shù)據(jù)部分和數(shù)據(jù)部分。元數(shù)據(jù)負責存放相對于中間部分的索引,數(shù)據(jù)部分存放真實的value。分割的節(jié)點為(pivot point)。它的將數(shù)據(jù)以及對應(yīng)的數(shù)據(jù)位置都保存在一個線性的數(shù)組中。使用的時候只需要把byte流發(fā)送出去,解析的時候只需要根據(jù)保存的位置,截取對應(yīng)的數(shù)值即可。
例子:
假設(shè)我們創(chuàng)建了一個Person對象,它的name是John,friendshipStatus是2.那么對應(yīng)圖中元數(shù)據(jù)部分第一個byte是1--->從中心點處數(shù)一個位置,開始的字符就是name的值即john。第二個byte是6,從中心點數(shù)6個位置值是2.
class Person {
String name;//john
int friendshipStatus;//2
Person spouse;
List<Person>friends;
}
從圖中可以看出來,flatbuffer將索引和數(shù)據(jù)文件存在一個一位數(shù)組中通過查找,還原對象,所以不需要打包和拆包的過程相對高效。
參考學習鏈接
1、https://www.jianshu.com/p/8df23cd182ec
2、https://www.jianshu.com/p/fa999434776a
3、https://google.github.io/flatbuffers/flatbuffers_guide_tutorial.html
總結(jié)
以上是生活随笔為你收集整理的flatbuffer介绍和用法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sata express接口
- 下一篇: 修改美化Matlab字体