全称: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;
}