protocol buffer 编码

protocol buffer能够跨平台提供轻量的序列化和反序列化,得益于其平台无关的编码格式,本文就介绍下其中的编码格式。

Varints

在protocol buffer中大量使用到了Varints的编码格式,这是一个可变长度的编码格式用于编码整形数字。
Varint的最小单位是byte,即8位,每byte第一位(msb)是标志位用于标记是否还有后续byte。

===1===
0000 0001
===300===
1010 1100  0000 0010

上面300的例子首先读入第一个字节发现第一位为1,表示还有后续byte,然后读取后一个byte,第一位为0就判断已经读完,然后组装数值将其余位数取出0101100 0000010,然后反转并拼接成为000 0010-010 1100,这样就组成了300。

其他类型

负数,sint与int

在protocol buffer的定义中sint和int似乎看上去是重复的,但其实这两种类型的底层编码式不同的。这里以-3为例:
-3使用int编码会变成FD FF FF FF FF FF FF FF FF 01,首先这也是varint编码去掉每个byte的首位标志位然后反转顺序就成了FF FF FF FF FF FF FF FD是-3的补码。
而使用sint编码会变成05,貌似和-3没有关系,其实它是-3经过一个zigzag转换而得来的。

Signed Original Encoded As
0 0
-1 1
1 2
-2 3
2147483647 4294967294
-2147483648 4294967295

这样转换可以大大减少负数的表示长度,所以建议在经常出现负数的地方使用sint而不是int可以缩短编码的大小。

非varient数值

对于double/fixed64,float/fixed32会分别使用固定的64位或32位进行表示。

不定长数据类型

对于string,byte等类型,就使用这种类型,首先使用一个varint表示长度,之后是数据的内容,列入字符串aaa就是03 61 61 61 其中03表示长度为3,61是a的utf8编码。值得注意的是,嵌套的message类型、repeat字段也都是使用这种形式进行编码到对象中的。

message编码

有了上面这些在准备,我们可以进入真正的消息的编码了。protocol buffer中每个字段都是根据定义的tag来进行定位的,在序列化的数据中,每个字段首先是一个Varint用于标记tag,其中最后三位使用来标志该字段的数据类型。

Type Meaning Used For
0 Varint int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 64-bit fixed64, sfixed64, double
2 Length-delimited string, bytes, embedded messages, packed repeated fields
3 Start group groups (deprecated)
4 End group groups (deprecated)
5 32-bit fixed32, sfixed32, float

前面的位数用于标志tag,例如0000 1000,去掉第一个标志位后三个类型位,就表示tag为1的字段。
对于repeat类型由于历史原因,proto2中默认是将数组元素并排排列在内的例如[1,2,3]会保存成[08 01 08 02 08 03]。后来对repeat类型进行了改进引入packed在定义的后面加上packed:

repeated int32 int = 1 [packed=true];

这样序列化的数据就成了0A 03 01 02 03,其中0A表示使用不定长编码,之后03表示长度,接下来是数据,就这个例子就能节约1byte。packed只适用于varint或固定长度数值表示的字段,对于string或者嵌套类型不适用,在proto3中支持的类型默认会使用packed。

实例

syntax = "proto2";
message Person {
    required string name=1;
    required int32 age=2;
    repeated Address add=3;
}
message Address{
    required string add=1;
}
---实例---
name: "MyName"
age: 18
add {
  add: "MyAdd1"
}
add {
  add: "MyAdd2"
}
---Hex---
0A 06 4D 79 4E 61 6D 65 10 12 1A 08 0A 06 4D 79 41 64 64 31 1A 08 0A 06 4D 79 41 64 64 32
---解释---
0A                      //变长类型tag为1的字符串
06                      //name字段6 byte长度
4D 79 4E 61 6D 65       //MyName
10                      //varint编码tag为2
12                      //18
1A                      //变长类型tag为3
08                      //Adress 8 byte长度
0A                      //变长类型tag为1
06                      //add字段6 byte长度
4D 79 41 64 64 31       //MyAdd1
1A                      //变长类型tag为3
08                      //Adress 8 byte长度
0A                      //变长类型tag为1
06                      //add字段6 byte长度
4D 79 41 64 64 32       //MyAdd2

原文地址:https://www.cnblogs.com/dwxt/p/8780198.html

时间: 2024-11-10 17:02:12

protocol buffer 编码的相关文章

Protocol Buffer编码方式

[toc] 本文翻译自: https://developers.google.com/protocol-buffers/docs/encoding 注:1.本文并非逐字逐句翻译,仅仅按照原文结构,以及知识点进行翻译,文章某些顺序以及描述方式将会被本人修改. 2.阅读本文之前需要对protocol buffer有一定认识,参见protocol buffer语法 主要介绍protocol buffer的二进制编码格式.在使用protocol buffer的时候这些可以不用理会,但是这些知识会让我们了

Protocol buffer序列化及其在微信蓝牙协议中的应用

Protocol buffer是Google出品的一种轻便高效的结构化数据存储格式,可对结构化数据进行序列化,并具有语言无关.平台无关等特点,在通信协议和数据存储等领域已经得到广泛的应用.目前其已经提供 C/C++.Java.Python 等语言的 API. 一.Protocol buffer和XML 在数据通信传输时,一般需要将结构化的数据序列化成流进行传送,接收方再反序列化为原始格式数据进行处理.在Web通信领域,XML应用算是最通用的了.在时间性能上,虽然XML的序列化开销还可以,但是反序

Protocol Buffer技术详解(语言规范)

Protocol Buffer技术详解(语言规范) 该系列Blog的内容主体主要源自于Protocol Buffer的官方文档,而代码示例则抽取于当前正在开发的一个公司内部项目的Demo.这样做的目的主要在于不仅可以保持Google文档的良好风格和系统性,同时再结合一些比较实用和通用的用例,这样就更加便于公司内部的培训,以及和广大网友的技术交流.需要说明的是,Blog的内容并非line by line的翻译,其中包含一些经验性总结,与此同时,对于一些不是非常常用的功能并未予以说明,有兴趣的开发者

Go语言使用Protocol Buffer的小例子

Protocol Buffer与Golang出自同门.Golang对其的支持包在https://github.com/golang/protobuf 下. 弄个小例子. 1. 创建proto文件usermsg.proto  package pfmsg; option java_package = "com.example.pfmsg"; option java_outer_classname = "UserMessage"; enum UserStatus { OF

protocol buffer 整数序列化

http://blog.csdn.net/csfreebird/article/details/7624807 varints用于正整数 (无符号整数) varints 是 一个很不错的技术.将一个整数序列化成1或者多个字节.想起以前我们总是使用4字节表示整数,真的很浪费啊.只有真正追求完美的人才会重视每个细节. 我的本篇介绍是https://developers.google.com/protocol-buffers/docs/encoding中的Base 128 Varints一节的逆过程.

序列化笔记之一:Google的Protocol Buffer格式分析

从公开介绍来看,ProtocolBuffer(PB)是google 的一种数据交换的格式,它独立于语言,独立于平台.作为一个学了多年通信的人,ProtocolBuffer在我看来是一种信源编码.所谓信源编码,就是将待传输的信源符号经过某种变换,转换成码流进行传输的这个变换过程.信源编码可分为两类:有损编码与无损编码,PB自然是属于无损编码,在无损编码中,又分为定长编码和变长编码,定长编码就是一个符号变换后的码字的比特长度是固定的,比如ASCII.Unicode都是定长编码,码字是8比特,16比特

【Google Protocol Buffer】Google Protocol Buffer

http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/ Google Protocol Buffer 的使用和原理 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它可用于通讯协议.数据存储等领域的语言无关.平台无关.可扩展的序列化结构数据格式.目前提供了 C++.Java.Python 三种语言的 API. 17 评论: 刘 明, 软件工程师, 上海交大电

Protocol Buffer基本介绍

转自:http://www.cnblogs.com/stephen-liu74/archive/2013/01/02/2841485.html 该系列Blog的内容主体主要源自于Protocol Buffer的官方文档,而代码示例则抽取于当前正在开发的一个公司内部项目的Demo.这样做的目的主要在于不仅可以保持Google文档的良好风格和系统性,同时再结合一些比较实用和通用的用例,这样就更加便于公司内部的培训,以及和广大网友的技术交流.需要说明的是,Blog的内容并非line by line的翻

快来看看Google出品的Protocol Buffer,别仅仅会用Json和XML了

前言 习惯用 Json.XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 事实上 是 Google出品的一种轻量 & 高效的结构化数据存储格式,性能比 Json.XML 真的强!太! 多! 由于 Google出品,我相信Protocol Buffer已经具备足够的吸引力 今天,我将献上一份 Protocol Buffer的介绍 & 使用攻略,希望你们会喜欢. 文件夹 1. 定义 一种 结构化数据 的数据存储格式(相似于 `XML.J