转载

ProtoBuffer----数据的varint编解码

优点:

a. 该数据接口编码出的数据占用内存空间小,约是json的30%~40%。
b. 传输效率高,耗费流量少,因为是字节码,编解码效率,也比json从字节码转换成对象流更快。
c. 传输过程的安全性也有所提高,因为是字节码,抓包器抓到的也只是字节二进制数据。
d. 支持多种语言的编译:c c++ java python c#等等。
e. 编写的proto数据结构文件,前后端都通用。
复制代码

缺点:

a. 因为是google的产品,通用性和xml和json比相对较差。
b. 如果传输的数据,数据结构比较复杂,编写proto的数据结构文件会复杂啰嗦,且教容易出错。
复制代码

使用场景:

protobuffer被用在很多领域:数据传输、游戏开发的数据通信、大数据领域的数据存储压缩、即时通讯IM(QQ、微信)

数据类型

在protobuffer的IDL文件中(int32, int64, uint32, uint64, sint32, sint64, bool, enum)这些数据类型使用varint来编码

编解码的详细过程(举栗子):

varint编码过程:在java中int需要4个字节,对于小于256的整型数字protobuf通过int32类型来表示,用varint编码只需要1个字节。 虽然大的数字需要更多的字节,但是统计表明大多数情况都是较小的数字,varint编码可以用更少的字节来表示数字,从而更好的压缩数据。

// 有300个学生
int32 studentNums = 300;

300的二进制:java中int为4个字节,32位
步骤一:‭‭0000 ‭0000 ‭0000 ‭0000  0000 0001 0010 1100‬  // 原始数据300转换成二进制
				       010 1100  // 将字节串的末尾取出7位bit
				      1010 1100  // 因为前面一个字节还有数据,所以在当前7位bit的这个字节最高位补1
步骤二:‭‭0000 ‭0000 ‭0000 ‭0000  0000 0001 0010 1100
			      00 0001 0          // 因为前面一个字节还有数据,再取出字节串的这7bit
			     000 0001 0	  // 因为前面字节没有数据了,最高位补0
步骤三:把步骤一和步骤二提取生成的字节串拼接
因为采用了小端字节序,所以步骤一低位字节放在高位地址,步骤二高位字节放在地位地址
 (步骤一)     (步骤二)
1010 1100 ++ 000 0001 0 ===> 1010 1100 0000 0010
将原来int32表示的4字节值:300  经过varint编码==> 2字节的  压缩了数据
复制代码

varint解码:10101100 00000010(两个字节的字节数组) ===> 解码后为:300(4个字节的原始数据)

1010 1100 0000 0010
 010 1100  000 0010  // 把每个字节的最高位去掉
 ========  ========
		 ||		将两个字节调换
		 ||
 000 0010  010 1100  // 把去掉高位后的两个字节调换
		 || // 编码时采用了小端字节序,而java正常采用的是大端字节序读取模式,所以解码时要调换字节  
		 ||	// 高低位字节调换后,合并就是 300的二进制值了
100101100  => 1  00 1 0  1   1 0 0
	     256  + 32 + 8 + 4 = 300复制代码
原文  https://juejin.im/post/5df21376e51d455810541255
正文到此结束
Loading...