提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
一、protobuf简介
protobuf(protocal buffer)是一种序列化数据结构的方法。其特点有:
1.支持多种语言(本文使用的是C++),多个平台。
2.类比于XML更小、更快、更简单。
3.扩展性、兼容性好。可以更新数据结构,而不破坏原有的结构和程序。
二、使用步骤
1.
编写 .proto ⽂件,⽬的是为了定义结构对象(message)及属性内容。
2.
使⽤ protoc 编译器编译 .proto ⽂件,⽣成⼀系列接⼝代码,存放在新⽣成头⽂件和源⽂件中。
3.
依赖⽣成的接⼝,将编译⽣成的头⽂件包含进我们的代码中,实现对 .proto ⽂件中定义的字段进⾏设置和获取,和对 message 对象进⾏序列化和反序列化。
1.创建.proto文件
文件命名应为全小写字母,多个词之间使用'_'间隔。
文件内容使用两个空格为缩进。
protoc3语法
指定proto3语法,和创建命名空间。
syntax = "proto3";
package namespace;
定义消息,消息类型名使用驼峰命名法,首字母大写。
message 消息类型名{
}
定义消息字段,字段定义格式为:字段类型 字段名 = 字段唯⼀编号。字段编号范围是1 ~ 536,870,911 (2^29 - 1),其中 19000 ~ 19999 不可⽤。
范围为 1 ~ 15 的字段编号需要⼀个字节进行编码, 16 ~ 2047 内的数字需要两个字节
进行编码。编码后的字节不仅只包含了编号,还包含了字段类型。所以 1 ~ 15 要⽤来标记出现常频
繁的字段,要为将来有可能添加的、频繁出现的字段预留⼀些出来。
message People{
string name = 1;
int age = 2;
}
2.编译proto文件
protoc [--proto_path=IMPORT_PATH] --cpp_out=OUT_DIR path/to/file.proto
protoc 是Protocol Buffer 提供的命令⾏编译⼯具。
--proto_path 指定被编译的.proto⽂件所在⽬录,可多次指定。可简写成 -I IMPORT_PATH 。如不指定该参数,则在当前⽬录进⾏搜索。当某个.proto ⽂件 import 其他 .proto ⽂件时,或需要编译的 .proto ⽂件不在当前⽬录下,这时就要⽤-I来指定搜索⽬录。
--cpp_out= 指编译后的⽂件指定为C++文件。
OUT_DIR 编译后⽣成⽂件的⽬标路径。
path/to/file.proto 要编译的.proto⽂件。
对于编译⽣成的 C++ 代码,包含了以下内容 :
对于每个 message ,都会⽣成⼀个对应的消息类。 在消息类中,编译器为每个字段提供了获取和设置⽅法,以及⼀下其他能够操作字段的⽅法。 编辑器会针对于每个 .proto ⽂件⽣成 .h 和 .cc ⽂件,分别用来存放类的声明与类的实现。
在消息类的⽗类 MessageLite 中,提供了读写消息实例的⽅法,包括序列化⽅法和反序列化⽅法
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);
};
3.使用序列化和反序列化
#include <iostream>
#include "contacts.pb.h" // 引⼊编译⽣成的头⽂件
using namespace std;
int main()
{
string people_str;
contacts::PeopleInfo people;
people.set_age(20);
people.set_name("张三");
// 调⽤序列化⽅法,将序列化后的⼆进制序列存⼊string中
if (!people.SerializeToString(&people_str))
cout << "序列化联系⼈失败." << endl;
contacts::PeopleInfo people;
// 调⽤反序列化⽅法,读取string中存放的⼆进制序列,并反序列化出对象
if (!people.ParseFromString(people_str))
cout << "反序列化出联系⼈失败." << endl;
}
}