protubuf序列化和反序列化原理

文章目录


protubuf序列化和反序列化原理

序列化: 将数据结构或者对象转换成二进制字节流

  1. 判断每个字段是否有设置值,有值才进行编码
  2. 根据字段表示号与实际类型将字段值通过不容的编码方式进行编码
  3. 将编码后的数据块按照字段类型采用不同的存储方式封装成二进制数据流

反序列化:将二进制字节流转换回数据结构或者对象

  1. 解析读取的二进制字节数据流
  2. 将解析出来的数据存储到c++、java等对应的数据结构中

varint编码:整形编码为长字节

很好记 var int 变长的int

​ 编码方法:把一个整数的二进制,每次取七位,最高位作为标志位,1表示后续字节还是当前数据的,0表示这是当前数据的最后一个数据,按照小端存储

111 1000100 1000000 // 七位一划分

倒序,前面加表示为,未结束就是1,结束了就是0;

11000000 11000100 00000111

参考上面的例子,原本四个字节的32位int数据就只占用了三个字节,节省了一个字节

  • 32位整形一般转化后需要1~5个字节,64位需要1-10个字节
  • 由于大部分的数据都没这么大,所以总体而言节省了很多内存

Zigzag编码:为了解决varint编码处理负数效率低的问题,实现原理:位移映射

也很好记 zigzag 之字形的,z是之字形的,映射表也是之字形的

通过映射表看非常简单:从零开始,然后负数正数交替,正数被扩大了两倍,中间的空隙正好存负数

原始正数 原始负数 Zigzag
0 0
-1 1
1 2
-2 3
2 4
-3 5
2147483647 4,294,967,294
- 2147483648 4,294,967,295

通过位运算编码:h(n) = (n << 1) ^ (n >> 31)

正数编码示例(以整数1为例)

  1. 数据位左移1位
    • 整数1的32位二进制补码表示为:0000 0000 0000 0000 0000 0000 0000 0001
    • 左移1位后得到:0000 0000 0000 0000 0000 0000 0000 0010
  2. 符号位右移31位
    • 由于1是正数,符号位为0,右移31位后得到:0000 0000 0000 0000 0000 0000 0000 0000
  3. 按位异或操作
    • 将左移结果和右移结果进行按位异或:0000 0000 0000 0000 0000 0000 0000 0010 ^ 0000 0000 0000 0000 0000 0000 0000 0000 = 0000 0000 0000 0000 0000 0000 0000 0010
    • 所以,整数1经过Zigzag编码后的值为2。

负数编码示例(以整数 -1 为例)

  1. 数据位左移1位
    • 整数 -1 的32位二进制补码表示为:1111 1111 1111 1111 1111 1111 1111 1111
    • 左移1位后得到:1111 1111 1111 1111 1111 1111 1111 1110
  2. 符号位右移31位
    • 由于 -1 是负数,符号位为1,右移31位后得到:1111 1111 1111 1111 1111 1111 1111 1111
  3. 按位异或操作
    • 将左移结果和右移结果进行按位异或:1111 1111 1111 1111 1111 1111 1111 1110 ^ 1111 1111 1111 1111 1111 1111 1111 1111 = 0000 0000 0000 0000 0000 0000 0000 0001
    • 所以,整数 -1 经过Zigzag编码后的值为1

你可能感兴趣的:(c++11,c++,开发语言,算法,linux,服务器)