【從0開發(fā)搭建App】Google Protocol Buffers淺析

本文主要偏向于介紹怎么使用Google的Protocol Buffer技術(shù)來壓縮與解析你的數(shù)據(jù)文件,更加詳細(xì)的信息請參閱Google開放的開發(fā)者網(wǎng)頁文檔,地址為:http://code.google.com/apis/protocolbuffers/docs/overview.html 。

一、簡單的介紹

當(dāng)然,在繼續(xù)本文之前,讀者還是需要對Google Protocol Buffers有一些基本的認(rèn)識。Protocol buffers是一個用來序列化結(jié)構(gòu)化數(shù)據(jù)的技術(shù),支持多種語言諸如C++、Java以及Python語言,可以使用該技術(shù)來持久化數(shù)據(jù)或者序列化成網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)。相比較一些其他的XML技術(shù)而言,該技術(shù)的一個明顯特點(diǎn)就是更加節(jié)省空間(以二進(jìn)制流存儲)、速度更快以及更加靈活。

通常,編寫一個protocol buffers應(yīng)用需要經(jīng)歷如下三步:

1、定義消息格式文件,最好以proto作為后綴名

2、使用Google提供的protocol buffers編譯器來生成代碼文件,一般為.h和.cc文件,主要是對消息格式以特定的語言方式描述

3、使用protocol buffers庫提供的API來編寫應(yīng)用程序

二、定義Proto文件

proto文件即消息協(xié)議原型定義文件,在該文件中我們可以通過使用描述性語言,來良好的定義我們程序中需要用到數(shù)據(jù)格式。首先我們可以通過Google在線文檔上提供的一個電話簿的例子來了解下,不過稍微加了點(diǎn)改動。

復(fù)制代碼

message Person {

required string name = 1;

required int32 id = 2;

optional string email = 3;

enum PhoneType {

MOBILE = 0;

HOME = 1;

WORK = 2;

}

message PhoneNumber {

required string number = 1;

optional PhoneType type = 2 [default = HOME];

}

repeated PhoneNumber phone = 4;

required bytes? unsure = 5;? ? ? //Add byte array here

}

message AddressBook {

repeated Person person = 1;

}

復(fù)制代碼

誠如你看到的一樣,消息格式定義很簡單,對于每個字段而言都有一個修飾符(required/repeated/optional)、字段類型(bool/string/bytes/int32等)和字段標(biāo)簽(Tag)組成。

三個修飾符從詞義上可以很清楚的弄明白,

1)對于required的字段而言,初值是必須要提供的,否則字段的便是未初始化的。在Debug模式的buffer庫下編譯的話,序列化話的時候可能會失敗,而且在反序列化的時候?qū)τ谠撟侄蔚慕馕鰰偸鞘〉?。所以,對于修飾符為required的字段,請?jiān)谛蛄谢臅r候務(wù)必給予初始化。

2)對于optional的字段而言,如果未進(jìn)行初始化,那么一個默認(rèn)值將賦予該字段,當(dāng)然也可以指定默認(rèn)值,如上述proto定義中的PhoneType字段類型。

3)對于repeated的字段而言,該字段可以重復(fù)多個,google提供的這個addressbook例子便有個很好的該修飾符的應(yīng)用場景,即每個人可能有多個電話號碼。在高級語言里面,我們可以通過數(shù)組來實(shí)現(xiàn),而在proto定義文件中可以使用repeated來修飾,從而達(dá)到相同目的。當(dāng)然,出現(xiàn)0次也是包含在內(nèi)的。

其中字段標(biāo)簽標(biāo)示了字段在二進(jìn)制流中存放的位置,這個是必須的,而且序列化與反序列化的時候相同的字段的Tag值必須對應(yīng),否則反序列化會出現(xiàn)意想不到的問題。

三、編譯proto文件,生成特定語言數(shù)據(jù)的數(shù)據(jù)定義代碼

在定義好了proto文件,就可以將該文件作為protocol buffers編譯器的輸入文件,編譯產(chǎn)生特定語言的數(shù)據(jù)定義代碼文件了。本文主要是針對C++語言,所以使用編譯器后生成的是.h與.cc的代碼文件。對于C++、Java還有Python都有各自的編譯器,下載地址:http://code.google.com/p/protobuf/downloads/list

當(dāng)你下載完了對應(yīng)的編譯器二進(jìn)制文件后,就可以使用下列命令來完成編譯過程:

protoc.exe -proto_path=SRC --cpp_out=DST SRC/addressbook.proto

其中--proto_path指出proto文件所在的目錄,--cpp_out則是生成的代碼文件要放的目錄,最后的一個參數(shù)指出proto文件的路徑。如上述命令中可以看出,將SRC目錄下的addressbook.proto編譯后放在DST目錄下,應(yīng)該會生成addressbook.pb.h和addressbook.pb.cc文件(/Files/royenhome/addressbook.rar)。

通過查看頭文件,可以發(fā)現(xiàn)針對每個字段都會大致生成如下幾種函數(shù),以number為例:

復(fù)制代碼

// required string number = 1;

inline bool has_number() const;

inline void clear_number();

inline const ::std::string& number() const;

inline void set_number(const ::std::string& value);

inline void set_number(const char* value);

inline ::std::string* mutable_number();

復(fù)制代碼

可以看出,對于每個字段會生成一個has函數(shù)(has_number)、clear清除函數(shù)(clear_number)、set函數(shù)(set_number)、get函數(shù)(number和mutable_number)。這兒解釋下get函數(shù)中的兩個函數(shù)的區(qū)別,對于原型為const std::string &number() const的get函數(shù)而言,返回的是常量字段,不能對其值進(jìn)行修改。但是在有一些情況下,對字段進(jìn)行修改是必要的,所以提供了一個mutable版的get函數(shù),通過獲取字段變量的指針,從而達(dá)到改變其值的目的。

而對于字段修飾符為repeated的字段生成的函數(shù),則稍微有一些不同,如phone字段,則編譯器會為其產(chǎn)生如下的代碼:

復(fù)制代碼

// repeated .Person.PhoneNumber phone = 4;

inline int phone_size() const;

inline void clear_phone();

inline const ::google::protobuf::RepeatedPtrField< ::Person_PhoneNumber >& phone() const;

inline ::google::protobuf::RepeatedPtrField< ::Person_PhoneNumber >* mutable_phone();

inline const ::Person_PhoneNumber& phone(int index) const;

inline ::Person_PhoneNumber* mutable_phone(int index);

inline ::Person_PhoneNumber* add_phone();

復(fù)制代碼

可以看出,set函數(shù)變成了add函數(shù),這個其實(shí)很好理解。上面也說過,repeated修飾的字段在高級語言中的實(shí)現(xiàn)可能是個數(shù)組或動態(tài)數(shù)組,所以當(dāng)然通過添加的方式來加入新的字段值。而起get函數(shù)也變化很大,這個也不用多說了。

好了,本文主要是對了解protocol buffer作了些簡單的介紹,當(dāng)然更詳細(xì)的還是看官方文檔。下篇文章開始將介紹怎么利用protocol buffers來完成序列化與反序列化數(shù)據(jù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容