为什么如此高效?解密kryo各个数据类型的序列化编码机制,强( 三 )
正确表示长度的编码规则(int) , 第8位(高位)表示字符串的编码 , 第7位(高位)表示是否还需要重新读取一个字节 , 也就是结束标记 , 1表示未结束 , 0表示结束 。 一个字节共8位 , 只有低6位放置了数据 , varint采取的是小端序列 。
代码@ 6:如果当前缓存区有足够的空间 , 先尝试将字符串中单字节数据写入到缓冲区中 , 碰到第一个非单字节字符时 , 结束 。
代码@ 7:将剩余空间写入缓存区 , 其实现方法:Output#writeString_slow(value , charCount , charIndex)
输出#writeString_slow
private void writeString_slow (CharSequence value, int charCount, int charIndex) {for (; charIndex < charCount; charIndex++) {// @1if (position == capacity) require(Math.min(, charCount - charIndex));// @2int c = value.charAt(charIndex);// @3if (c <= 0x007F) {// @4buffer[position++] = (byte)c;} else if (c > 0x07FF) {// @5buffer[position++] = (byte)(0xE0 | c >> 12require(2);buffer[position++] = (byte)(0x80 | c >> 6buffer[position++] = (byte)(0x80 | c} else {// @6buffer[position++] = (byte)(0xC0 | c >> 6require(1);buffer[position++] = (byte)(0x80 | c}} }
代码@ 1:循环遍历字符的字符 。
代码@ 2:如果当前缓存区已经写满 , 尝试申请(capacity与charCount-charIndex)的替换 , 此处无需担心字符不是单字节申请charCount-charIndex空间不足的问题 , 后面我们会详细分析require方法 , 字节不足时会触发缓存区扩容或刷写到流中 , 再重复利用缓存区 。
代码@ 3:int c = value.charAt(charIndex); 将字符类型转换为int类型 , 一个中文字符对应一个int数字 , 这是因为java使用unicode编码 , 每个字符占用2个字节 , char向int类型转换 , 就是将2个字节的字节编码 , 转换成对应的二进制 , 然后用10个二进制表示的数字 。
代码@ 4:如果值小于等0x7F(127) , 直接存储在1个字节中 , 此时高位4个字节的范围在(0-7) 。 ] 。
代码@ 5:如果值大于0x07FF(二进制0000 0111 1111 1111) , 第一个大于0x7F的变量(0000 1000 0000 0000) , 即2 ^ 12 , 数据有效位至少12位 , 使用3字节来存储 , 具体存储方式为:
1)buffer [0]:buffer [position ++] =(byte)(0xE0 | c >> 12&0x0F); 首先将c右移12位再与0x0F进行与操作 , 其意义就是先提取c的第16-13(4位的值) , 并与0xE0取或 , 最终的数值0xE(16-13)位的值 , 从输入中读取字符串可以研磨 , 是根据0xE0作为存储该字符需要3个字节的依据 , 并且只取16-13位的值作为其高位的有效位 , 从而字符编码的值 , 不会超过0XFFFF , 也就是两个字节(正好与java unicode编码吻合) 。
2)buffer [1]:存储第12-7(共6位) , c >> 6&0x3F , 然后与0X80进行或 , 高位设置为1 , 表示UTF-8编码 , 其实再反序列化时 , 这个高位设置为1 , 未有实际作用 。
3)buffer [2]:存储第6-1(共6位) , 0x80 | c&0x3F , 同样高位置1 。
2.2字符串反序列化(byte [] ----> String)在讲解反序列化时 , 总结一下字符串序列化的编码规则
String序列化规则:String序列化的整体结构为length +内容 , 注意 , 这里的length不是内容字节的长度 , 而是String字符的长度 。
- 如果是null , 则用1个字节表示 , 其二进制为1000 0000 。
- 如果是“”空字符串 , 则用1个字节表示 , 其二进制为1000 0001 。
- 如果字符长度大于1且小于64 , 并且字符全是ascii字符(小等于127) , 则每个字符用一个字节表示 , 最后一个字节的高位置1 , 表示字符串字符的结束 。 【优化点 , 如果是ascii字符 , 编码时不需要使用length +内容的方式 , 或者直接写入内容】
- 如果不满足上述条件 , 则需要使用length +内容的方式 。
- 用一个变长int写入字符的长度 , 每个字节 , 高两个分别为编码标记(1:utf8) , 是否结束标记(1:否; 0:结束) 2)将内容用utf-8编码的字符串序列中 , utf8 , 用变长字节(1-3)个字节表示一个字符(英文 , 中文) 。 每一个字节 , 使用6为 , 高两位为标志位 。 【16位】 3字节的存储为【4位】+【6位】+【6位】 , 根据第一个字节高4位判断得出需要几个字节来存储一个字符 。
3 , 布尔类型序列化【为什么如此高效?解密kryo各个数据类型的序列化编码机制,强】实现类为DefaultSerializers $ BooleanSerializer , 序列化:使用1个字节存储boolean类型 , 如果为true , 则写入1 , 否则写入0 。
- 看不上|为什么还有用户看不上华为Mate40系列来看看内行人怎么说
- 设置|iPhone拍照小技巧:保留常用设置更高效
- 制药领域|为什么AI制药这么火,为什么是现在?
- 手机壳里头|为什么要在手机壳里面夹钱?10个有9个不懂,我才知道大有讲究
- 短视频|全球最火APP?抖音爆火背后离不开这几剂“猛药”为什么抖音能够这么火?
- 电商快递|包邮不香吗,为什么还有人加49元让小哥穿西装专车送快递?
- 团队|为什么项目管理非常重要?
- 猫腻|为什么拼多多上商品价格那么便宜还包邮?有什么猫腻?看完明白了
- 加拿大|上演戏剧性一幕!iPhone12最新售价确定,苹果也没想到降价如此快
- 刷机|前几年满大街的“刷机”服务去哪里了,为什么大家都不爱刷机了?