Google Protocol Buffers淺析(一)

    本文主要偏向於介紹怎麼使用Google的Protocol Buffer技術來壓縮與解析你的數據文件,更加詳細的信息請參閱Google開放的開發者網頁文檔,地址爲: http://code.google.com/apis/protocolbuffers/docs/overview.html 。

     1、簡單的介紹html

     固然,在繼續本文以前,讀者仍是須要對Google Protocol Buffers有一些基本的認識。Protocol buffers是一個用來序列化結構化數據的技術,支持多種語言諸如C++、Java以及Python語言,可使用該技術來持久化數據或者序列化成網絡傳輸的數據。相比較一些其餘的XML技術而言,該技術的一個明顯特色就是更加節省空間(以二進制流存儲)、速度更快以及更加靈活。api

     一般,編寫一個protocol buffers應用須要經歷以下三步:數組

     一、定義消息格式文件,最好以proto做爲後綴名網絡

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

     三、使用protocol buffers庫提供的API來編寫應用程序  ui

 

     2、定義Proto文件 google

     proto文件即消息協議原型定義文件,在該文件中咱們能夠經過使用描述性語言,來良好的定義咱們程序中須要用到數據格式。首先咱們能夠經過Google在線文檔上提供的一個電話簿的例子來了解下,不過稍微加了點改動。     spa

複製代碼
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 ;
}
複製代碼

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

     三個修飾符從詞義上能夠很清楚的弄明白,code

    1)對於required的字段而言,初值是必需要提供的,不然字段的即是未初始化的。在Debug模式的buffer庫下編譯的話,序列化話的時候可能會失敗,並且在反序列化的時候對於該字段的解析會老是失敗的。因此,對於修飾符爲required的字段,請在序列化的時候務必給予初始化。

    2)對於optional的字段而言,若是未進行初始化,那麼一個默認值將賦予該字段,固然也能夠指定默認值,如上述proto定義中的PhoneType字段類型。

    3)對於repeated的字段而言,該字段能夠重複多個,google提供的這個addressbook例子便有個很好的該修飾符的應用場景,即每一個人可能有多個電話號碼。在高級語言裏面,咱們能夠經過數組來實現,而在proto定義文件中可使用repeated來修飾,從而達到相同目的。固然,出現0次也是包含在內的。      

    其中字段標籤標示了字段在二進制流中存放的位置,這個是必須的,並且序列化與反序列化的時候相同的字段的Tag值必須對應,不然反序列化會出現意想不到的問題。

    

     3、編譯proto文件,生成特定語言數據的數據定義代碼  

     在定義好了proto文件,就能夠將該文件做爲protocol buffers編譯器的輸入文件,編譯產生特定語言的數據定義代碼文件了。本文主要是針對C++語言,因此使用編譯器後生成的是.h與.cc的代碼文件。對於C++、Java還有Python都有各自的編譯器,下載地址:http://code.google.com/p/protobuf/downloads/list  

     當你下載完了對應的編譯器二進制文件後,就可使用下列命令來完成編譯過程:

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

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

     經過查看頭文件,能夠發現針對每一個字段都會大體生成以下幾種函數,以number爲例:

複製代碼
   //  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();
複製代碼

      能夠看出,對於每一個字段會生成一個has函數(has_number)、clear清除函數(clear_number)、set函數(set_number)、get函數(number和mutable_number)。這兒解釋下get函數中的兩個函數的區別,對於原型爲const std::string &number() const的get函數而言,返回的是常量字段,不能對其值進行修改。可是在有一些狀況下,對字段進行修改是必要的,因此提供了一個mutable版的get函數,經過獲取字段變量的指針,從而達到改變其值的目的。

      而對於字段修飾符爲repeated的字段生成的函數,則稍微有一些不一樣,如phone字段,則編譯器會爲其產生以下的代碼: 

複製代碼
   //  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();
複製代碼

      能夠看出,set函數變成了add函數,這個其實很好理解。上面也說過,repeated修飾的字段在高級語言中的實現多是個數組或動態數組,因此固然經過添加的方式來加入新的字段值。而起get函數也變化很大,這個也不用多說了。

     好了,本文主要是對了解protocol buffer做了些簡單的介紹,固然更詳細的仍是看官方文檔。下篇文章開始將介紹怎麼利用protocol buffers來完成序列化與反序列化數據。

原文出處:http://www.cnblogs.com/royenhome

相關文章
相關標籤/搜索