FlatBuffers入門簡介

最近有項目用到了FlatBuffer净嘀,本文就以極簡的方式介紹FlatBuffers的環(huán)境配置和使用方式奏寨。
作者使用MAC OSX操作系統(tǒng)抖部,使用IDEA開發(fā)工具《В可能讀者環(huán)境與作者有所不同践惑,但無論是什么環(huán)境,整體思路和步驟是相似的嘶卧,希望本文能給讀者有所幫助尔觉。

一、FlatBuffers簡介

FlatBuffers為Google發(fā)布的一個跨平臺芥吟,提供多種語言接口穷娱,注重性能和資源使用的序列化類庫绑蔫。目前該類庫提供C++, C#, C, Go, Java, JavaScript, PHP, and Python語言接口。該序列化類庫多用于移動端手游數(shù)據(jù)傳輸以及特定的對性能有較高要求的應用泵额。
接下來我們將學習FlatBuffers環(huán)境搭建并且使用Java語言完成一次簡單的序列化例子配深。

  • 編譯flatc工具
  • 編寫一個FlatBuffers的scheme文件
  • 使用flatc工具編譯scheme文件,生成對應語言的數(shù)據(jù)對象頭文件/類
  • 使用FlatBufferBuilder序列化對象
  • 反序列化數(shù)據(jù)對象

二嫁盲、編譯flatc工具

FlatBuffers源碼工程在CMake/文件夾下為我們提供了*.cmake文件篓叶,方便我們使用Cmake工具編譯工程生成flatc工具。

2.1 Cmake環(huán)境配置

Cmake官網(wǎng)下載制定平臺的二進制安裝包羞秤,筆者為MAC OSX平臺所以直接下載dmg格式的安裝文件缸托,讀者可根據(jù)自身平臺下載相應的二進制安裝包。當然讀者也可以直接下載具體平臺的源碼進行編譯瘾蛋。
下載安裝完成后需要將cmake命令加入PATH下俐镐,筆者使用zsh的shell,因此相關(guān)的配置文件在~/.zshrc文件下,如果讀者使用不同shell,請在正確的位置配置哺哼。

 export CMAKE_HOME=/Applications/CMake.app/Contents
 export PATH=$CMAKE_HOME/bin:$PATH

其中/Applications/CMake.app/Contents為Cmake的安裝根目錄佩抹,讀者需根據(jù)具體安裝位置進行修改。
然后運行如下命令將最新加載最新配置:

source .zshrc

重新啟動終端輸入如下命令

cmake --help

若看到如下信息則證明配置完成:

Usage

  cmake [options] <path-to-source>
  cmake [options] <path-to-existing-build>

......//省略更多的信息

2.2 下載FlatBuffers源碼

從gitHub上下載項目源代碼:

git clone git@github.com:google/flatbuffers.git

2.3 編譯取董、安裝flatc

進入flatbuffers項目根目錄棍苹,輸入如下命令:

cmake -G "Unix Makefiles"

稍等一會cmake就完成了MakeFile的生成,接下來運行:

make

開始編譯茵汰,稍等一會編譯成功后會在根目錄下生成flatc工具枢里。
接下來我們使用

make install

命令,安裝flatc蹂午,該命令將flatc工具拷貝到/usr/local/bin/目錄下(環(huán)境配置不同可能有所不同)栏豺,重新啟動終端輸入

flatc --version

命令會打印當前flatc的版本信息,筆者輸出結(jié)果如下:

flatc version 1.6.0

至此豆胸,我們完成了flatc工具的編譯和安裝冰悠。

三、編寫FlatBuffers的scheme文件

本文使用官網(wǎng)教程里面的例子配乱,筆者進行了整理并加入自己的理解和說明溉卓。

// Example IDL file for our monster's schema.
namespace com.zeyuan.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;

我們對上述文件進行簡要說明。整個文件配置方式偏向類C的方式第一行namespace定義了該scheme的命名空間搬泥,在JAVA環(huán)境下為包名桑寨。然后使用enum關(guān)鍵字定義類枚舉類型Color,使用union定義共用體(C風格),struct定義了名為Vec3的結(jié)構(gòu)體忿檩,table定義了名為Monster復合類結(jié)構(gòu)尉尾,其中它包含定義的結(jié)構(gòu)體、共用體燥透、枚舉等沙咏。最后root_type指明Monster類為根類型辨图。當然這里我們只是很簡單的講解了scheme的含義,如果想具體了解語法知識可查看寫一個scheme這篇官網(wǎng)文檔肢藐。

四故河、編譯scheme文件

將上節(jié)編寫的scheme文件保存為monster.fbs文件,到該文件所在文件夾下吆豹,執(zhí)行

flatc --java monster.fbs

將會生成Java語言的類文件定義鱼的,如果你想為別的語言生成相應的類文件可查看該文檔

五痘煤、代碼示例

創(chuàng)建一個普通的java工程凑阶,你有兩種方式引入FlatBuffers的相關(guān)語言的API:

  • 將FlatBuffers源碼下java文件夾內(nèi)容拷貝到項目工程源碼路徑下;
  • 或者 使用Maven或Gradle項目管理工具從Maven倉庫下載Jar包衷快。

筆者使用Gradle創(chuàng)建項目宙橱,因此在項目build.gradle文件內(nèi)依賴關(guān)系配置如下:

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    // https://mvnrepository.com/artifact/com.github.davidmoten/flatbuffers-java
    compile 'com.github.davidmoten:flatbuffers-java:1.6.0.2'
}

工程測試代碼如下:

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);
        }
    }
}

上述代碼主要是使用FlatBufferBuilder完成對象序列化然后將序列化的二進制數(shù)據(jù)反序列化并打印出來。代碼中對關(guān)鍵部分都增加了代碼注釋都伪,這里就不再詳細解釋帶嗎細節(jié)了。

至此我們完成了FlatBuffers工具的入門积担,讀者可以直接下載示例代碼以便加深理解陨晶。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市帝璧,隨后出現(xiàn)的幾起案子先誉,更是在濱河造成了極大的恐慌,老刑警劉巖的烁,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褐耳,死亡現(xiàn)場離奇詭異,居然都是意外死亡渴庆,警方通過查閱死者的電腦和手機铃芦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來襟雷,“玉大人刃滓,你說我怎么就攤上這事∷逝” “怎么了咧虎?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長计呈。 經(jīng)常有香客問我砰诵,道長征唬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任茁彭,我火速辦了婚禮总寒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尉间。我一直安慰自己偿乖,他們只是感情好,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布哲嘲。 她就那樣靜靜地躺著贪薪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眠副。 梳的紋絲不亂的頭發(fā)上画切,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音囱怕,去河邊找鬼霍弹。 笑死,一個胖子當著我的面吹牛娃弓,可吹牛的內(nèi)容都是我干的典格。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼台丛,長吁一口氣:“原來是場噩夢啊……” “哼耍缴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挽霉,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤防嗡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后侠坎,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚁趁,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年实胸,在試婚紗的時候發(fā)現(xiàn)自己被綠了他嫡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡庐完,死狀恐怖涮瞻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情假褪,我是刑警寧澤署咽,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響宁否,放射性物質(zhì)發(fā)生泄漏窒升。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一慕匠、第九天 我趴在偏房一處隱蔽的房頂上張望饱须。 院中可真熱鬧,春花似錦台谊、人聲如沸蓉媳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酪呻。三九已至,卻和暖如春盐须,著一層夾襖步出監(jiān)牢的瞬間玩荠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工贼邓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留阶冈,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓塑径,卻偏偏與公主長得像女坑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子统舀,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容