本文的主要内容是google protobuf中序列化数据时用到的编码规则,但是,介绍具体的编码规则之前,我觉得有必要先简单介绍一下google protobuf。因此,本文首先会介绍一些google protobuf相关的内容,让读者朋友对google protobuf有一个初步的印象,然后,再开始进入正题—-深入浅出地介绍google protobuf中用到的编码规则。下面言归正传,开始今天的话题。
1. Google-ProtoBuf是什么
ProtoBuf,全称是Protocol Buffers, 它是谷歌内部用的一种高效的、可扩展的对结构化数据进行编码的格式规范。谷歌自己内部很多程序之间的通信协议都用了ProtoBuf。
ProtoBuf可以支持多种编程语言,目前已经C++, Java和Python,本文中所前的内容用到例子的话,会以C++为例。
2.如何得到Google-ProtoBuf
ProtoBuf在Google Code上的主页是:http://code.google.com/p/protobuf/, 感兴趣的朋友可以在这里下载ProtoBuf的源码,也可以在这里阅读ProtoBuf的详细的文档。
3. 深入浅出Google-ProtoBuf中的编码规则
(1)序列化和反序列化:
在开始本部分的内容之前,首先有必要介绍两个基本概念,一个是序列化,一个是反序列化。这两个概念的定义在网上搜一下都很多的,但大多都讲得比较晦涩,不太好理解,在这里我会用比较通俗的文字来解释,尽可能让读都朋友们一读就明白是怎么回事:
序列化:是指将结构化的数据按一定的编码规范转成指定格式的过程
反序列化:是指将转成指定格式的数据解析成原始的结构化数据的过程
举个例子,Person是一个表示人的对象类型,person是一个Person类型的对象,将person存到一个对应的XML文档中的过程就是一种序列化,而解析XML生成对应Person类型对象person的过程,就是一个反序列化的过程。在这里结构化数据指的就是Person类型的数据,一定的编码规范指的就是XML文档的规范。XML是一种简单的序列化方式,用XML序列化的好处是,XML的通用性比较好,另外,XML是一种文本格式,对人阅读比较友好,但是XML方式比较占空间,效率也不是很高。通常,比较高效的序列化都是采用二进制方式的,将要序列化的结构化数据,按一定的编码规范,转成为一串二进制的字节流存储下来,需要用的时候再从这串二进制的字节流中反序列化出对应的结构化的数据。
通过上面的介绍,我们给protobuf下一个比较正式的定义了:Google ProtoBuf是Google制定的一种用来序列化结构化数据的程序库。
(2)ProtoBuf中的编码:
1) ProtoBuf编码基础——Varints, varints是一种将一个整数序列化为一个或者多个Bytes的方法,越小的整数,使用的Bytes越少。
Varints的基本规则是:
(a) 每个Byte的最高位(msb)是标志位,如果该位为1,表示该Byte后面还有其它Byte,如果该位为0,表示该Byte是最后一个Byte。
(b)每个Byte的低7位是用来存数值的位
(c)Varints方法用Litte-Endian(小端)字节序
举个例子:300用Varints序列化的结果是1010 1100 0000 0010,运算过程如下 所示:
1010 1100 0000 0010->010 1100 000 0010(去标志位)->
000 0010 010 1100(调整字节序)-> 1 0010 1100 ->256+32+8+4=300(计算值)
2)ProtoBuf中消息的编码规则:
(a)每条消息(message)都是有一系列的key-value对组成的, key和value分别采用不同的编码方式。
(b)对某一条件消息(message)进行编码的时候,是把该消息中所有的key-value对序列化成二进制字节流;而解码的时候,解码程序读入二进制的字节流,解析出每一个key-value对,如果解码过程中遇到识别不出来的类型,直接跳过。这样的机制,保证了即使该消息添加了新的字段,也不会影响旧的编/解码程序正常工作。
(c)key由两部分组成,一部分是在定义消息时对字段的编号(field_num),另一部分是字段类型(wire_type)。字段类型定义如下表所示。
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 |
(d)key的编码方式:field_num << 3 | wire_type
(e)varint类型(wire_type=0)的编码,与第(1)部分中介绍的方法基本一致,但是int32, int64和sint32,sint64有些特别之处:int32和int64就是简单的按varints方法来编码,所以像-1、-2这样负数也会占比较多的Bytes。于是sint32和sint64采用了一种改进的方法:先采用Zigzag方法将所有的整数(正数、0和负数)一一映射到所有的无符号数上,然后再采用varints编码方法进行编码。Zigzag映射函数为:
Zigzag(n) = (n << 1) ^ (n >> 31), n为sint32时
Zigzag(n) = (n << 1) ^ (n >> 63), n为sint64时
下表是一个比较直观的映射表,这样映射后再进行编码的好处就是绝对值比较小的负数序列化后的结果占的Bytes数也会比较少。
Signed Original
Encoded As
0 |
0 |
-1 |
1 |
1 |
2 |
-2 |
3 |
2 |
4 |
-3 |
5 |
… |
… |
2147483647 |
4294967294 |
-2147483648 |
4294967295 |
(f)64-bit(wire_type=1)和32-bit(wire_type=5)的编码方式就比较简单了,直接在key后面跟上64bits或32bits,采用Little-Endian(小端)字节序。
(g)length-delimited(wire_type=2)的编码方式:key+length+content, key的编码方式是统一的,length采用varints编码方式,content就是由length指定的长度的Bytes。
(h)wire_type=3和4的现在已经不推荐使用了,因此这里也不再做介绍。
3)ProtoBuf编解码中字段顺序(Field order)的问题:
(a) 编码/解码与字段顺序无关,这一点由key-value机制就能保证
(b)对于未知的字段,编码的时候会把它写在序列化完的已知字段后面。
分享到:
相关推荐
`lua-protobuf` 是一个专门为 Lua 语言设计的模块,它使得在 Lua 环境中能够方便地使用 Google 的 Protocol Buffers(protobuf)进行数据序列化和反序列化。protobuf 是一种高效的数据表示语言,广泛用于网络通信、...
1. **消息解析与编码**:库提供了对protobuf消息的解析和编码功能,允许开发者将protobuf定义的结构化数据转化为字节流,或者从字节流中恢复数据。 2. **类型检查**:在编码和解码过程中,pure_protobuf会进行严格的...
protobuf是一种轻量级的数据序列化协议,由Google开发,用于结构化数据的存储和交换。它允许开发者定义数据结构,并在各种语言之间进行高效的序列化和反序列化。 描述中的“高效消息压缩格式 protobuf3 语法详解 ...
Protocol Buffers(简称protobuf)是Google开发的一种数据序列化协议,用于高效地存储和传输结构化数据。它提供了一种语言中立、平台中立、机器中立的方式来定义数据结构,使得不同系统之间可以轻松地交换数据。...
在构建高效、低延迟的数据传输系统时, ProtoBuffer(Protocol Buffers)作为一种轻量级的结构化数据序列化协议,被广泛应用于微信小程序的通信和数据存储中。本文将详细介绍ProtoBuffer及其在微信小程序中的具体...
protobuf(Protocol Buffers)是Google开发的一种数据序列化协议,它允许开发者定义数据结构,然后将结构化的数据序列化为二进制流,便于存储、通信或者在网络上传输。protobuf的核心理念是提供一种高效、灵活且易于...
它能够将结构化数据序列化,可用于数据存储、通信协议等方面。`protobuf-java`则是protobuf在Java平台上的实现库,它提供了编译器和运行时库,使得Java开发者可以方便地使用protobuf进行数据序列化和反序列化。 ###...
protobuf(Protocol Buffers)是由Google公司开发的一种高效的数据序列化协议,它允许开发者定义数据结构,然后将数据编码为紧凑的二进制格式,用于存储数据或者在网络间进行高效的数据传输。protobuf 2.5.0 是该...
Protobuf(Protocol Buffers)是Google推出的一种数据序列化协议,它提供了一种高效、灵活且自动化的结构化数据序列化方法,类似于XML和JSON,但更小、更快、更简单。在Java开发中,protobuf2.5.0 jar包是用于处理...
Protocol Buffers(protobuf)是Google推出的一种数据序列化协议,用于结构化数据的编码和解码。protobuf的优点包括高效、跨平台和语言无关。 1. **定义消息类型**:使用.proto文件定义消息结构,包括字段类型、...
2. **protobuf**:全称为Protocol Buffers,是Google开发的一种数据序列化协议,可以将结构化数据序列化,可用于网络通信、数据存储等,具有高效、灵活、跨语言的特点。protobuf 2.5相较于2.4可能增加了新的功能或...
- **数据存储**:在数据库中存储结构化数据,提高存储效率。 - **配置文件**:创建易于理解和解析的配置格式。 ### 5. 相关工具 - **protoc-gen-go**:针对Go语言的protobuf编译插件,生成Go语言的结构体和方法。 ...
**protobuf与protoc详解** protobuf(Protocol Buffers)是由Google开发的一种...通过protobuf定义数据结构,protoc生成各种编程语言的接口,开发者可以轻松地在不同环境中处理结构化数据,提高系统性能和可维护性。
Protobuf(Protocol Buffers)是Google推出的一种数据序列化协议,它提供了一种语言中立、平台中立、可扩展的方式来组织数据,类似于XML和JSON,但更高效、更小且更快。在3.20.2版本中,我们关注的是其性能优化、新...
protobuf通过定义`.proto`文件,用户可以声明结构化的数据类型,如消息、枚举和服务。这些定义被编译成特定语言(如C++、Java、Python等)的源代码,便于在应用中使用。 ### 2. `.proto` 文件 在protobuf中,`....
- **数据存储**: 存储结构化数据,如数据库记录、日志文件等。 - **配置文件**: 提供紧凑、易于解析的配置格式。 - **序列化对象**: 在内存中持久化或跨进程传递对象状态。 总结,protobuf开源代码为开发者提供了一...
1. **Google Protocol Buffers (protobuf)**: Google开源的一种数据序列化协议,它可以将结构化的数据序列化,可用于数据存储、通信协议等方面。protobuf提供了高效的编码和解码机制,并且支持多种编程语言,包括C++...
Protocol Buffers(简称Protobuf)是由Google开发的一种高效的数据序列化协议,它提供了一种平台无关、语言无关、可扩展的方式,使得数据能够被不同系统之间共享和交换。 **Protobuf的基本概念** 1. **定义消息...
`protobuf`(Protocol Buffers)是由Google开发的一种高效的数据序列化机制,它支持多种编程语言,并能以紧凑的形式存储结构化的数据。`protobuf`不仅被广泛应用于Google内部的大量项目中,也被开源社区所采纳,成为...
Google的Protocol Buffers(protobuf)是一种数据序列化协议,用于结构化数据的编码和解码。相比XML或JSON,protobuf更紧凑、更快、更易于解析。在cdeer-im项目中,protobuf可能用于定义IM服务之间的消息协议,使...