java编码与protobuf使用
OutputStreamWriter 转换字符到字节,同样 StreamEncoder 类负责将字符编码成字节,编码格式和默认编码规则与解码是一致的。
?2>内存操作
? ? ? String s = "字符串。。。";
? ? ? byte[] bt = s.getBytes("UTF-8");
? ? ? String str = new String(bt,"UTF-8");
?? ? ?String 类就提供转换到字节的方法,也支持将字节转换为字符串的构造函数。
Charset 提供 encode 与 decode 分别对应 char[] 到 byte[] 的编码和 byte[] 到 char[] 的解码。如下代码所示:
?
d、使用protoc命令进行编译

?
2>序列化和反序列化分析
1、package与optionjava_package同时存在,后者会取代前者 。
java代码生成相关参考:https://developers.google.com/protocol-buffers/docs/reference/java-generated?hl=zh-CN
2、PB数据类型
? required: a well-formed message must have exactly one of this field.
? optional: a well-formed message can have zero or one of this field (but not more than one).
? repeated: this field can be repeated any number of times (including zero) in a well-formed message. ? ? ? ? ? ? ? ? ? ?The order of the repeated values will be preserved.
类型参考https://developers.google.com/protocol-buffers/docs/proto?hl=zh-CN&csw=1
3、message的编码特点
? ? ? ? ?PB之所以解析速度快、所占体积小,很大程度上是由它序列化的编码特点来决定的。
3.1 Base 128 Varints
? ? ? ? PB采用了Base 128 Varints来变长编码整数:
? ? 变长编码的整数,它可能包含多个byte,对于每个byte的8位,其中后7位表示数值,最高的一位表示是否还有还有另一个byte,0表示没有,1表示有;
越前面的byte表示数值的低位,越后面的byte表示数值的高位;
?
例子:
300 ??varints? 编码为:1010 1100 0000 0010
解释如下:
300的2进制编码为:0001 0010 1100
按照刚才的规则,高低位颠倒,截取最后的7为放在第一个byte,则第一byte为1010 1100(其中最高位1表示,后续还有byte);接着剩下的内容放到第二个byte,为0000 0010(其中最高位0表示,后续无byte,这个数到这里截止了)。
于是,合在一起为 1010 1100 0000 0010;
PB将 key编码成下面的结构:?
X?YYYY?ZZZ
其中:最高位X表示是否还有后续的byte来编码数字别名;YYYY用于编码别名,定义了多于16个属性,则需要用到额外的byte,所以出现频率高的字段应当取1-16的别名);ZZZ表示这个字段的类型,PB支持的属性的对应规则如下表:

?3.2具体实例分析
如下图所示,针对上述定义的proto文件及序列化后的字节流进行分析

? ? ? ? ? ? ? byte[0]: ?10 ? ? ? ? ??0 0001 010 别名1,类型repeated
? ? ? ? ? ? ??byte[1]: ?14 ? ? ? ? ?一个对象所占字节数
? ? ? ? ? ? ??byte[2]: ?8 ? ? ? ? ? 0?0001 000 missionId
? ? ? ? ? ? ? byte[3]: ?16 ? ? ? ? 0 0010 000 missionUserId
? ? ? ? ? ? ??byte[4]: ?24 ? ? ? ? 0 0011 000 status
? ? ? ? ? ? ??byte[5]: ?32 ? ? ? ? 0 0100 000 finishedTime
? ? ? ? PB具有跨平台、解析速度快、序列化数据体积小、扩展性高、使用简单的特点。但是我们也可以看到,相比于XML,PB的数据,并不是自然可读的;同时它生成的代码不是纯pojo,对于代码有一定的侵入性。例如pb不支持像Map<Long, 0bject>,其中Object会出现多种不确定的类型,这样就无法通过pb序列化。从上述分析的数据可以看出,protobuf采用的k-v存储结构,并且采用变长的字节编码格式,所以从空间效率比较高。