ProtoBuf学习笔记

什么是ProtoBuf


一种数据存储、传输格式,用于结构化数据,主要的优点有结构紧凑、占用空间小、结构化速度快、扩展性良好,同时平台、语言无关。

使用步骤


1. 定义proto文件(结构描述)
2. 生成对应语言的实现(JAVA等)
3. 生成数据端将数据结构化为Proto格式数据流
4. 接收端解析数据
例:http://blog.csdn.net/wanyanxgf/article/details/8817925

proto文件定义


option java_package:生成Java文件的package
option java_outer_classname:生成的Java文件名
message:定义一个message,相当于java的class
enum:定义一个枚举,相当于Java的枚举
required:表示此字段必须存在,即在结构化的流当中必须存在此字段,否则不能反解析
optional:此字段表示可选,可以有也可以没有
repeated:代表此字段可以出现0~n次,可以认为是一个Java中的list
default:代表默认值,此值不在流中体现,即接收端解析后的默认值是和接收端的类中定义的是一样的,和发送端的无关
字段后面的数字:字段的数字表示,在流中表示字段,定义之后不能改变(因为存储方式关系,尽量使用15因为的)

常用字段类型(和Java中对应):
double==>double
float==>float
bool==>bool
string==>String
bytes==>byte[]
int32/uint32/sint32==>int(uint32为无符号,因为int32的存储方式导致对负数的处理较为耗资源,所以引入sint32,对负数处理较好)
int64/uint64/sint64==>long(同上)
fixed*==>int,long(用固定长度来存储,在数字较大的时候使用动态方式处理较耗资源使用比较好)
option java_package = "com.meituan.service.mobile.protobuf.hotel";
option java_outer_classname = "HotelCommentProto";

message HotelCommentList{
        repeated HotelComment comments=1;
}


message HotelComment{
        required int64 id=1;
        optional int64 poi_id=2;
        optional int64 did=3;
        optional int64 user_id=4;
        optional string user_name=5;
        optional int32 score=6 [default=5];
        optional string score_text=7;
        optional string comment=8;
        optional int64 feedback_time=9;
        optional HotelType ht=10;
}
 enum HotelType {
    NORMAL = 0;
    EXP = 1;
  }


Encoding


先解释下varints,是一种用一个到多个byte表达 integers的方式
1. 将一个数字转成2进制,从低位起每7个bit一组,如:150=000001 0010110
2. 从低到高取bit组,如果后面还有bit组则在第一位补充1,如果没有则补充0。【1】000001 【0】0010110

示例一

//定义
required int32 a = 1;
//赋值
a=150;

encode结果:

08 96 01

二进制为:

00001000 10010110 0000001

分析:

根据varints规则,上述结果为2组byte

byte组1:00001000

代表字段的定义,规则为:(field_number << 3) | wire_type
由此规则判断:第一个bit【0】代表没有后续byte组,后三个byte【000】代表wire type为0(wire type下面再解释),中间几位代表字段的数字表示【0001】,为1
注:这个描述可以解释上面说的字段的数字描述尽量使用15以内的,如果超过15,则字段的定义无法用一个byte表示,需要多个byte。

byte组2:10010110 0000001

根据规则两个byte的第一个bit位【1】、【0】分别代表后面还有和后面没有了
因为数字生成时是低位在前,所以还原需要把byte反排下,【000001】【0010110】,10010110=128+16+4+2=150

不同的wire type代表不同的结构化方式:


type=0:即采用上述描述的varints规则
type=1,5:已经明确指定数据长度,存储采用低位在前的方式
type=2:以String举例
//定义
required string b = 2;
//赋值
b=testing

结果为:

12 07 74 65 73 74 69 6e 67

byte组1:12=00010010

表示type=2,字段编号=2

byte组2:07=00000111

表示后面有7个byte是这个字段的value

byte组3:74 65 73 74 69 6e 67

value utf-8编码后的值

repeated的存储

optional int64 user_id=4;
如果此字段有多个值,最后的流中会出现多个 4:value1,4:value2的结果对(不一定是挨在一起的),在解析时在组合到一起
optional int64 user_id=4[packed=true];
存储方式类似string,如:22 06 02 8e 02,其中【22】为字段定义,【06】为后续数据长度,后面为数据。

变更的影响


1. 所有字段的数字表示不可变更
2. 新增的字段是required,如果生产方和解析方版本不一致,则无法解析
3. 新增的字段是optional或者repeated。如生产方使用新版本,旧版本的解析方抛弃新增字段的值。如生产方使用旧版本,新版本的解析方无相关数据填充
4. 非required字段删除,影响同3(不建议)
5. 修改字段类型,int32, uint32, int64, uint64, bool可以相互解析,不过可能会发生数据截断
6. 修改字段类型,string、bytes之间可以互相解析(bytes都为utf-8可解析)
7. 修改字段修饰符,生产方的该字段为repeated,而解析方为optional,可以解析。如果是基本类型或者是string,则解析时使用最后一个值(每次都是后一个覆盖前一个),如果是其他类型(message等),会执行merge,即多个message属性合并,都存在的以后一个为准。

Java代码生成规则


  1. 对每一个message生成一个*OrBuider的接口和一个message的
  2. *OrBuider接口中主要是对message属性的获取方法
  3. message的类实现*OrBuilder接口同时继承GeneratedMessage,message类不能直接修改。必须使用其内部的builder构建。
  4. 内部builder中包含message类的写方法



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!关于学习 Protocol Buffers(protobuf),您可以从以下几个方面入手: 1. 官方文档:首先,您可以查阅 Protocol Buffers 的官方文档,它提供了详细的说明、示例和教程,可以帮助您了解 protobuf 的基本概念和用法。官方文档地址为:https://developers.google.com/protocol-buffers/docs/overview。 2. 安装和使用:接下来,您可以按照官方文档中的指引,安装 Protocol Buffers 工具集,并学习如何使用 protobuf 编译器(protoc)生成指定语言的代码。您可以选择使用 C++、Java、Python 等支持 protobuf 的编程语言进行学习和实践。 3. 语法和消息定义:了解 protobuf 的语法和消息定义是非常重要的。您可以学习如何定义消息类型、字段和其他高级特性,以及如何使用扩展、嵌套消息等。官方文档中有详细的说明和示例,帮助您掌握这些概念。 4. 应用场景:除了基本的语法和消息定义,了解 protobuf 在实际应用中的使用也是很重要的。您可以了解如何在网络通信中使用 protobuf 进行数据传输,如何进行数据序列化和反序列化,以及如何处理不同语言之间的兼容性等问题。 5. 其他资源:除了官方文档,还有一些其他的学习资源可以帮助您更深入地学习和应用 protobuf。例如,可以阅读相关的书籍、博客文章,参与开源项目和社区讨论等。 希望以上信息对您有所帮助!如果您有其他问题,我会尽力回答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值