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 編譯器的安裝。