Protobuf
ProtoBuf(全称Protocol Buffer)是数据结构序列化和反序列化框架(谷歌开发)
它具有以下特点:
- 语⾔⽆关、平台⽆关:即 ProtoBuf ⽀持 Java、C++、Python 等多种语⾔,⽀持多个平台
- ⾼效:即⽐ XML (数据交换格式)更⼩、更快、更为简单
- 扩展性、兼容性好:你可以更新数据结构,⽽不影响和破坏原有的旧程序(根据我们的需要自己生成需要的结构)
使用方法
- 编写的.proto文件,自定义结构对象及属性内容(描述对象中,有什么样的成员,每个成员具有什么样的属性。比如描述学生结构:姓名:字符串、学号:长整形、。。。)
-
编译proto文件:使用protoc编译器编译.proto文件中的描述,生成对应的接口代码,存放在新生成头文件和源文件中。
- .h 中定义了我们所描述的数据结构对象类;
- .cc定义实现了结构化对象的访问&操作&序列化&反序列化
- 使用:引入生成的头文件,在代码中根据需要使用即可。依赖⽣成的接⼝,将编译⽣成的头⽂件包含进我们的代码中,实现对. proto ⽂件中定义的字段进⾏设置和获取,和对 message 对象进⾏序列化和反序列化
编写的.proto文件
.proto文件规范:
- 创建.proto⽂件时,⽂件命名应该使⽤全⼩写字⺟命名 ,多个字⺟之间⽤_ 连接。例如:lower_snake_case.proto
- 书写.proto⽂件代码时,应使⽤2个空格的缩进(推荐而已不强制)
语法规则:
必须写:
1. 指定proto3语法(声明语法版本):syntax = "proto3";
2. package声明符(声明命名空名称):
相当于命名空间,避免我们定义的消息出现冲突package 根据情况命名 package contacts;
3. 定义结构化对象描述(定义结构化对象描述)
可以理解为类
message 消息类型名{
各个字段描述: 字段类型 字段名 = 字段唯一编号;
}
例:
message contact{
uint64 sn = 1;//学号
string name = 2;//姓名
float score = 3;//成绩
}
其中Protobuf的类型太多了就一一列出来了,建议有需求就直接搜。
编译contacts.proto文件
编译命令行格式为:
protoc [--proto_path=IMPORT_PATH] --cpp_out=DST_DIR path/to/file.proto
1. protoc 是 Protocol Buffer 提供的命令⾏编译⼯具。
2. --proto_path 指定 被编译的.proto⽂件所在⽬录,可多次指定。可简写成 -IIMPORT_PATH 。如不指定该参数,则在当前⽬录进⾏搜索。当某个.proto ⽂件 import 其他.proto ⽂件时,或需要编译的 .proto ⽂件不在当前⽬录下,这时就要⽤-I来指定搜索⽬录。
3. --cpp_out= 指编译后的⽂件为 C++ ⽂件。
4. OUT_DIR 编译后⽣成⽂件的⽬标路径。
5. path/to/file.proto 要编译的.proto⽂件
6. [ ] 表示可以不写
例如生成c++的方法:
protoc --cpp_out=. contacts.proto
实操 protoc编译.proto文件(附图 也可以直接看这快速了解):
- 编写.proto文件:
//声明proto语法版本
syntax = "proto3";
package contacts;
message Contact{
uint64 sn = 1;
string name = 2;
float score = 3;
}
2. 编译.proto文件
protoc --cpp_out=. contacts.proto
1. protoc必备
2. --cpp_out:表示生成c++文件
3. ‘.’:表示生成的路径(当前路径)
4. contacts.proto 要编写的proto文件)`
输出后就会生成两个文件:
了解生成的代码
常用接口(序列化、反序列化):
成员的get获取接口和set设置接口:
常用接口:
class MessageLite {
public:
//序列化:
bool SerializeToOstream(ostream* output) const; // 将序列化后数据写⼊⽂件流
bool SerializeToArray(void *data, int size) const;
bool SerializeToString(string* output) const;
//反序列化:
bool ParseFromIstream(istream* input); // 从流中读取数据,再进⾏反序列化动作
bool ParseFromArray(const void* data, int size);
bool ParseFromString(const string& data);
};
实操使用生成的文件:
-
创建contact类对象 conn
- 设置学号、姓名、成绩
-
序列化string str(存起来的是二进制的!)
通过conn对象的SerializeAsString函数序列化的数据 -
反序列化获取数据在contact stu对象中:
使用ParseFromString反序列化返回bool值- 判断失败—返回-1
- 成功—打印存在的 stu 的成员对象
-
创建makefile
- g++编译(略)
- 注意需要连接protobuf库(-l连接外部库)-lprotobuf
#include <iostream>
#include "contacts.pb.h"
#include "contacts.pb.cc"
int main()
{
contacts::contact conn;
conn.set_sn(251);
conn.set_name("坤坤");
conn.set_score(91);
std::string str = conn.SerializeAsString();
contacts::contact stu;
int n = stu.ParseFromString(str);
if(n == -1){
std::cout << "获取失败"<<std::endl;
}
else{
std::cout << stu.sn() << std::endl;
std::cout << stu.name() << std::endl;
std::cout << stu.score() << std::endl;
}
return 0;
}