protobuf-介紹篇

What are protocol buffers?


protobuf 是 protocol buffers的簡稱,它是結構體數據序列化的協議方法,簡單、靈活、高效、自動,更重要的是它垮平臺、支持多種語言(目前支持java、c++、python)。類似 XML,但是比 xml 更小、更快速、更簡單。你可以一次定義特定的數據結構,然後編譯生產特定的語言代碼對象(例如java),然後在這種語言下你很方便的實現對這個數據結構進行讀和寫,並且在數據流中傳輸,然後實現跨語言快平臺的讀寫操作。


How do they work?


1 按照 protobuf 的語法定義你的數據結構,保存爲 .proto 文件。

例如:

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

數據結構很簡單,關於 protobuf 定義語法細節請參考:https://developers.google.com/protocol-buffers/docs/proto

一旦你定義好了你的 protobuf messages (數據結構),你可以使用 protobuf 的編譯器將 .proto 文件編譯生產製定語言的類文件,這個文件的成員變量和類型和 .proto 文件裏面定義的對應。例如,如果你選擇的是 c++ 語言,運行編譯器編譯上面的 .proto 文件,會生成一個叫做 Person 的類。然後你可以使用這個類進行序列化/反序列化的操作。例如:

Person person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("[email protected]");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output);
上面是將一個對象序列化寫到一個輸出管道中。然後再另一端你可以這樣讀回數據:

fstream input("myfile", ios::in | ios::binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
圖解:


爲啥不用 XML 就行了


關於數據結構的序列化,protobuf 有很多優點。
  • 結構更簡單
  • 佔用空間比 XML 小3~10倍
  • 速度比 XML 快10~20倍
  • 比 XML更少參數歧義
  • 生產語言原生數據對象更簡單

例如:現在定義一個 Person 對象,包含 name 和 email 兩個字段。用 XML 定義爲:

  <person>
    <name>John Doe</name>
    <email>[email protected]</email>
  </person>
使用 protobuf 定義爲:
# Textual representation of a protocol buffer.
# This is *not* the binary format used on the wire.
person {
  name: "John Doe"
  email: "[email protected]"
}
當上面的結構編碼成 protobuf 的二進制格式(上面的文本格式只是爲了便於人理解和調試,最終回編譯成機器能理解的二進制格式)之後,上面的數據大約九佔 28個字節的長度,解析速度達到100~200納秒;而上面的 XML 格式至少佔用69個字節以上,而且解析速度爲5000~10000納秒。

再看看這解析上面的便利性。protobuf 使用很簡單,語言對象的使用,例如:

cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
而 XML 的解析:
cout << "Name: "
       << person.getElementsByTagName("name")->item(0)->innerText()
       << endl;
cout << "E-mail: "
       << person.getElementsByTagName("email")->item(0)->innerText()
       << endl;
雖然 proto buf 有這麼多優點,但也不是任何場合下它都比 XML 好。例如在基於文本文檔模型的應用中它就不是太好用。在一個消息定義模型的應用中 protobuf 的使用意義更大。

文章參考:https://developers.google.com/protocol-buffers/docs/overview

-》下篇文章介紹 protobuf 編譯器的安裝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章