说明
- Protobuf全称是Google Protocol Buffer,是google开发的一种高效轻便的结构化数据存储方式,可用于数据通信、数据存储等,也可以理解为结构化数据的序列化方法;类似于xml,Json等。
与xml,json对比
- 三种都与语言无关,平台无关
- Protobuf支持Java, C++, Python等多种语言,支持多个平台。
- Protobuf是二进制格式比xml,json等字符串协议更高效,也比XML更小(3~10倍),效率更快(20 ~ 100倍)。
- 扩展性,兼容性好;可以更新数据结构,而不影响和破坏原有的旧程序。
- Protobuf操作更为简单,因为不仅仅有通用的接口,也能生成特例接口。
环境配置
https://github.com/protocolbuffers/protobuf
- 当前最新版本: Protocol Buffers v3.12.3
- 注意:v3和v2有很多不同的。
编译安装
./configure --prefix=/home/xxx/pb
make
make install
* /home/xxx/pb 是库安装路径
bin
bin/protoc //proto 文件编译工具
include //库头文件目录
lib //库文件目录,包含3个库文件
lib/libprotobuf.xxx //完整版,库大小较大
lib/libprotobuf-lite.xxx //精简版,库大小较小
lib/libprotoc.xxx
简单使用
- 创建数据结构描述文件(.proto文件),示例如下:
* 文件名example.proto
syntax = "proto3";
option optimize_for = LITE_RUNTIME;
message example
{
int32 id = 1;
string name = 2;
int32 age = 3;
}
protoc -I=./ --cpp_out=./ example.proto
* -I : 说明example.proto的文件路径
* --cpp_out : 数据操作代码生成路径
* 成功后会生成文件 example.pb.cc, example.pb.h
#include <iostream>
#include <fstream>
#include <string>
#include "example.pb.h" //引入前面生成的文件
int main() {
example example1;
example1.set_id(12);
example1.set_name("leon");
example1.set_age(14);
//将数据写入文件
std::string filename = "configure";
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);
}
output.close();
example example2;
//将数据从文件读出
std::fstream input("configure", std::ios::in|std::ios::binary);
if(!example2.ParseFromIstream(&input))
{
std::cerr << "Failed to parse address book." << std::endl;
return -1;
}
std::cout << example2.id() << " " << example2.name() << " " << example2.age() << std::endl;
return 0;
}
g++ -std=c++11 -I . -I ../include example.pb.cc test.cpp -L ../lib -lprotobuf-lite -lpthread -o test
* 不加 -lpthread,编译正常,但是运行时会崩溃报错
* protobuff3需要指定c++11,v2版本不需要
- Protocol Buffer定义了三种优化级别SPEED/CODE_SIZE/LITE_RUNTIME,缺省情况下是SPEED;通过proto文件中的option optimize_for 选择。
- SPEED: 表示生成的代码运行效率高,但是由此生成的代码编译后会占用更多的空间。
- CODE_SIZE: 和SPEED恰恰相反,代码运行效率较低,但是由此生成的代码编译后会占用更少的空间,通常用于资源有限的平台,如Mobile。
- LITE_RUNTIME: 生成的代码执行效率高,同时生成代码编译后的所占用的空间也是非常少,是以牺牲Protocol Buffer提供的反射功能为代价的,使用时也仅需链接libprotobuf-lite,而非libprotobuf。