《protobuf》入门

初始protobuf

Protocol Buffers 是 Google 的一种语言无关、平台无关、可扩展的序列化结构数据的 方法,它可用于(数据) 通信协议、数据存储等。

Protocol Buffers 类比于 XML,是一种灵活,高效,自动化机制的结构数据序列化 方法,但是比 XML 更小、更快、更为简单。

你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序

ProtoBuf(全称为 Protocol Buffer )是让结构数据序列化的方法,其具有以下 特点:

语言无关、平台无关:即 ProtoBuf支持Java、C++、Python多种语言,支持多个平台 。
高效:即比XML更小、更快、更为简单。
扩展性 、兼容性好:你可以更新数据结构,而不影响和破坏原有的旧程序

❓什么是序列化

在这里插入图片描述

简单上手

编写protobuf

  • 编写.proto文件
// 规定使用proto3语法标准,一定得在首行
syntax="proto3";
// 类似C++中的namespace,package是⼀个可选的声明符,能表示.proto⽂件的命名空间,在项⽬中要有唯⼀性。它的作⽤是为了避免我们定义的消息出现冲突
package=contacts;

// 消息类型命名规范:使⽤驼峰命名法,首字母大写
// message 消息体名称{}
message PeopleInfo
{
	string name = 1;
	int32 age = 2;
}

在 message 中,我们可以定义其属性字段,字段定义格式为: 字段类型 字段名 = 字段唯⼀编号

  • 字段名称命名规范:全小写字母,多个字母之间用 _ 连接。

  • 字段类型分为:标量数据类型特殊类型(包括枚举、其他消息类型等)。

  • 字段唯⼀编号:用来标识字段,一旦开始使用就不能够再改变。

字段唯⼀编号的范围
1 ~ 536,870,911(229-1),其中19000 ~ 19999不可用,做完保留字段

以下表格展示了标量数据类型,以及编译 .proto 文件之后自动生成的类中与之对应的字段类型。这里展示与C++语言对应的类型

TypeNotesC++ Type
doubledouble
floatfloat
int32使用变长编码[1]。负数的编码效率较低–若字段可能为负值,应使用 sint32 代替。int32
int64使用变长编码[1]。负数的编码效率较低–若字段可能为负值,应使用 sint64 代替。int64
uint32使用变长编码1uint32
uint64使用变长编码1uint64
sint32使用变长编码1。符号整型。负值的编码效率高于常规的 int32 类型。int32
sint64使用变长编码1。符号整型。负值的编码效率高于常规的 int64 类型。int64
fixed32定长 4 字节。若值常大于228则会比 uint32 更高效。uint32
fixed64定长 8 字节。若值常大于256 则会比 uint64 更高效。uint64
sfixed32定长 4 字节。int32
sfixed64定长 8 字节。int64
boolbool
string包含 UTF-8 和 ASCII 编码的字符串,长度不能超过 232string
bytes可包含任意的字节序列,长度不能超过 232string

编译 .proto 文件

在编写完 .proto 文件后,我们接着在终端对其进行编译

// 这里的.proto文件名称为 contacts
protoc --cpp_out=. contacts.proto

解释说明

protoc [--proto_path=IMPORT_PATH] --cpp_out=DST_DIR path/to/file.proto

在这里插入图片描述

cpp_out用来生成 C++ 代码,java_out产生 Java 代码,python_out产生 python 代码,类似地还有csharp_outobjc_outruby_outphp_out等参数。

在这里插入图片描述
成功编译如下
在这里插入图片描述

编写测试文件 testPB.cc

#include<iostream>
#include"contacts.pb.h"

int main()
{
	std::string people_str;
	{
		contacts::PeopleInfo people;
		people.setname("张三");
		people.setage("22");
		// 序列化后的内容是二进制,people_str只是载体,用于后面反序列化
		if(!people.SerializeToString(&people_str))  
		{
            std::cout<< "序列化失败!" << std::endl;
            return -1;
		}
        std::cout<< "序列化成功! 结果为:" << people_str << std::endl;
	}
	{
		contacts::PeopleInfo people;
		// 将people_str内容反序列化成原来的内容
		if(!people.ParseFromString(people_str))
		{
			std::cout<< "反序列化失败!" << std::endl;
            return -1;
		}
        std::cout<< "反序列化成功!" << std::endl;
        std::cout << people.name() << std::endl;
        std::cout << people.age() << std::endl;
	}
	return 0;
}
  • 编译,链接容易出现的坑
  1. 漏掉 -lprotobuf
  2. 漏掉 contacts.pb.cc

正确写法

g++ -o testPB testPB.cc contacts.pb.cc -lprotobuf -std=c++11

在这里插入图片描述


  1. 变长编码:经过protobuf 编码后,原本4字节或8字节的数可能会被变为其他字节数 ↩︎ ↩︎ ↩︎ ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值