Protobuf 是Google官方出品一種輕便高效的結構化數據存儲格式,可以用於結構化數據串行化,或者說是序列化。它很適合做數據存儲或RPC數據交換格式。可用於通訊協議、數據存儲等領域的平台無關、語言無關、可擴展的序列化結構數據格式。
優點
-
-
提供了友好的動態庫,使用簡單
-
解析速度快,比對應的XML快約20-100倍
-
使用 protobuf, 需要先書寫 .proto 文件,然后編譯該文件。編譯 proto 文件則需要使用官方的 protoc 工具。
// Filename: addressbook.proto syntax="proto2"; // 表明使用protobuf的編譯器版本為v2,目前最新的版本為v3 package addressbook; message Person { //message是Protobuf中的結構化數據,類似於C++中的類,可以在其中定義需要處理的數據 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; } message AddressBook { repeated Person person_info = 1; } /* 1,2,3 是字段的標識號,在消息定義中,每個字段都有唯一的一個數字標識號,這些標識號是用來在消息的二進制格式中識別各個字段的,一旦開始使用就不能夠再改變。 標識號的范圍在:1 ~ 229 - 1,其中[19000-19999]為Protobuf預留,不能使用。 Person 內部聲明了一個enum和一個message,這類似於C++中的類內聲明,Person外部的結構可以用 Person.PhoneType 的方式來使用PhoneType。當使用外部package中的結構時,要使用 pkgName.msgName.typeName 的格式,每兩層之間使用'.'來連接,類似C++中的"::"。 */
標量類型列表
proto類型 | C++類型 | 備注 |
double | double | |
float | float | |
int32 | int32 | 使用可變長編碼,編碼負數時不夠高效——如果字段可能含有負數,請使用sint32 |
int64 | int64 | 使用可變長編碼,編碼負數時不夠高效——如果字段可能含有負數,請使用sint64 |
uint32 | uint32 | 使用可變長編碼 |
uint64 | uint64 | 使用可變長編碼 |
sint32 | int32 | 使用可變長編碼,有符號的整型值,編碼時比通常的int32高效 |
sint64 | int64 | 使用可變長編碼,有符號的整型值,編碼時比通常的int64高效 |
fixed32 | uint32 | 總是4個字節,如果數值總是比總是比228大的話,這個類型會比uint32高效 |
fixed64 | uint64 | 總是8個字節,如果數值總是比總是比256大的話,這個類型會比uint64高效 |
sfixed32 | int32 | 總是4個字節 |
sfixed64 | int64 | 總是8個字節 |
bool | bool | |
string | string | 一個字符串必須是UTF-8編碼或者7-bit ASCII編碼的文本 |
bytes | string | 可能包含任意順序的字節數據 |
win10系統下,C++開發如何使用
https//github.com/protocolbuffers/protobuf/release/latest
2、解壓源碼到任意路徑下
path/protobuf-3.19.1
3、下載 CMake 工具
4、CMake生成 VS2019 工程
-
-
設置源碼路徑下的cmake目錄
path/protobuf-3.19.1/cmake
-
設置任意構建目錄
path/protobuf_build
-
點擊 configure、選擇對應 VS,編譯為 WINI32,編譯器默認
-
點擊Finish按鈕,開始自動編譯
-
點擊 Generate 生成VS項目
-
用 VS 打開生成的工程,按需要選擇編譯 libprotobuf、libprotobuf-lite、libprotoc和protoc項目
-
# 標准命令 protoc -I=./ --cpp_out=./ ./test.proto #--cpp_out 是輸出路徑, ./為當前路徑
-
-
拷貝 src目錄下的goole文件夾到當前項目的include目錄下
-
拷貝 libprotobuf.lib libprotoc.lib 到當前項目的 lib 目錄下
-
項目設置為多字節,添加靜態鏈接庫
-
C/C++ General Additional Include Directories 添加include目錄
-
Linker General Additional Library Directories 添加 lib 目錄
-
g++ main.cc xxx.pb.cc -I $INCLUDE_PATH -L $LIB_PATH -lprotobuf -pthread
protoc 為message的每個required字段和optional字段都定義了一下幾個函數,不限於這幾個
TypeName xxx() const; //獲取字段 // bool has_xxx(); //判斷是否設置值 pb 2 void set_xxx(const TypeName&); //設置 void clear_xxx(); //使其變為默認值
為每個 repeated 字段定義了以下幾個:
TypeName* add_xxx(); //增加結點 TypeName xxx(int) const; //獲取指定序號的結點,類似於c++的“[]”運算符 TypeName* mutable_xxx(int); //類似於上一個,但是獲取的是指針 int xxx_size(); //獲取結點的數量
幾個常用的序列化函數
bool SerializeToOstream(std::ostream * output) const; //輸出到輸出流中 bool SerializeToString(string * output) const; //輸出到string bool SerializeToArray(void * data, int size) const; //輸出到字節流
與之對應的反序列化函數
bool ParseFromIstream(std::istream * input); //從輸入流解析 bool ParseFromString(const string & data); //從string解析 bool ParseFromArray(const void * data, int size); //從字節流解析
其他常用函數
bool IsInitialized(); // 檢查是否所有required字段都被設值 size_t ByteSize() const; // 獲取二進制字節序的大小 pb2
官方API文檔: https://developers.google.com/protocol-buffers/docs/reference/overview
參考資料
https://www.cnblogs.com/autyinjing/p/6495103.html