全稱:protocol buffers
一種語言無關、平臺無關、可擴展的序列化結構數據的方法,它可用於(數據)通信協議、數據存儲等
一種靈活、高效,自動化機制的結構數據序列化方法-可類比XML,但是比XML更小(3-10倍)、更快(20-100倍)、更爲簡單。
體現:
可以定義數據的結構,然後使用特殊生成的源代碼輕鬆地在各種數據流中使用各種語言進行編寫和讀取結構數據,甚至可以更新數據結構,而不破壞由舊數據結構編譯的已部署程序
特點:
- 語言無關、平臺無關。即ProtoBuf支持Java、C++、Python等多種語言,支持多個平臺
- 高效。即比XML更小(3-10倍)、更快(20-100倍)、更爲簡單
- 擴展性、兼容性好。可以更新數據結構,而不影響和破壞原有的舊程序
使用:
- 創建.proto文件,定義數據結構
message xxx {
// 字段規則:required -> 字段只能也必須出現 1 次
// 字段規則:optional -> 字段可出現 0 次或1次
// 字段規則:repeated -> 字段可出現任意多次(包括 0)
// 類型:int32、int64、sint32、sint64、string、32-bit ....
// 字段編號:0 ~ 536870911(除去 19000 到 19999 之間的數字)
字段規則 類型 名稱 = 字段編號;
}
示例:
message Example1 {
optional string stringVal = 1;
optional bytes bytesVal = 2;
message EmbeddedMessage {
int32 int32Val = 1;
string stringVal = 2;
}
optional EmbeddedMessage embeddedExample1 = 3;
repeated int32 repeatedInt32Val = 4;
repeated string repeatedStringVal = 5;
}
- protoc編譯.proto文件生成讀寫接口
.proto文件中定義了數據結構,面向開發者和業務程序,並不面向存儲和傳輸。需要進行序列化、反序列化以及讀寫。
通過protoc編譯器實現
命令:
// $SRC_DIR: .proto 所在的源目錄
// --cpp_out: 生成 c++ 代碼
// $DST_DIR: 生成代碼的目標目錄
// xxx.proto: 要針對哪個 proto 文件生成接口代碼
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/xxx.proto
最終生成的代碼提供類似如下的接口:
bool SerializeToString(string* output) const; //將對象序列化爲二進制字符串
bool ParseFromString(const string& data); // 解析一個二進制字符串
bool SerializeToOstream(ostream* output) const; // 將對象序列化成ostream
bool ParseFromIstream(istream* input); //解析istream
例子生成的接口:
void clear_int32val();
void set_int32val(::google::protobuf::int32 value) //設置int32val值
::google::protobuf::int32 int32val() const; //獲取int32val值
void clear_stringval();
void set_stringval(const char* value); // 設置stringval值
const ::std::string& stringval() const; /// 獲取stringval值
- 調用接口實現序列化、反序列化以及讀寫
測試代碼:
//
// Created by yue on 18-7-21.
//
#include <iostream>
#include <fstream>
#include <string>
#include "single_length_delimited_all.pb.h"
int main() {
Example1 example1;
example1.set_stringval("hello,world");
example1.set_bytesval("are you ok?");
Example1_EmbeddedMessage *embeddedExample2 = new Example1_EmbeddedMessage();
embeddedExample2->set_int32val(1);
embeddedExample2->set_stringval("embeddedInfo");
example1.set_allocated_embeddedexample1(embeddedExample2);
example1.add_repeatedint32val(2);
example1.add_repeatedint32val(3);
example1.add_repeatedstringval("repeated1");
example1.add_repeatedstringval("repeated2");
std::string filename = "single_length_delimited_all_example1_val_result";
std::fstream output(filename, std::ios::out | std::ios::trunc | std::ios::binary);
if (!example1.SerializeToOstream(&output)) {
std::cerr << "Failed to write example1." << std::endl;
exit(-1);
}
return 0;
}