- 深入理解序列化与反序列化
- 潘洪安
- 911字
- 2020-11-21 19:41:45
1.3 Base64编码
在数据传输的场景中,如果都是英文字符,传输能正常进行;但如果出现非英文字符,如中文字符、日文字符、不可打印字符、多媒体文件等,则可能出现乱码。为了解决上述问题,Base64编码方案被提出。Base64编码基于8 bit分割,以可打印字符为最终体现形式完成对数据的编码。
1.3.1 编码规则
1)对原始数据按6 bit进行分割;如果当前所有bit长度不是6的整数倍,则有剩余bit。
2)对6 bit进行高位补齐2个0,凑成8 bit;在剩余bit前面补齐若干个0,凑成8 bit。
3)补齐后的每个字节称为索引,最大值为00111111(63),最小值为000000(0)。
4)根据索引表,将索引替换成目标字符。
1.3.2 解码规则
1)根据索引表,将字符替换成索引,每个索引为1个字节,对应8 bit。
2)将每个索引的前2个bit(值为00)去掉,剩余所有bit长度为N。
3)在小于等于N的范围内找到第一个最接近N且能被8整除的数M。
4)如果N和M相等,则说明编码之前的所有bit长度是6和8的公倍数,长度为N的所有bit按照8 bit切分即完成解码。
5)如果M<N,说明编码之前的所有bit长度不是6的整数倍,需要对长度为N的bit序列的最后一个6 bit块进行如下处理:去掉高位(N-M)个bit,剩余的M个bit按照8 bit切分即完成解码。
1.3.3 索引表
表1-5显示了完整的Base64索引表。
表1-5 Base64索引表
索引表的最后两个索引默认是+和/字符;在URL编码时,需要用-(横杠)和_(下画线)替代。
1.3.4 编码与解码示例
· 编码示例1:bit长度是6的整数倍
表1-6给出了待编码数据的bit长度能被6整除情况下的编码过程。
表1-6 bit长度是6的整数倍
续表
· 编码示例2:bit长度不是6的整数倍
表1-7给出了待编码数据的bit长度不能被6整除情况下的编码过程。
表1-7 bit长度不是6的整数倍
· 解码示例:Base64编码值为abI
表1-8给出了Base64的解码过程。
表1-8 Base64的解码过程
1.3.5 Java应用示例
· Java 1.8 Base64
从Java 1.8开始,JDK包含了java.util.Base64,应用示例如下。
代码注释中的数字表示编码后的字节数,读者可自行验证。
· commons-codec
commons-codec编码后的字节长度是8,这是因为内部实现默认使用了字节对齐的特性。
针对上述两种实现,笔者做了性能对比,Java 1.8的Base64实现更高效,对比数据如表1-9所示。
表1-9 Base64编码性能对比
值得一提的是,JDK很早就提供了sun.misc包下的BASE64Encoder和BASE64Decoder,能满足Base64编码和解码的需求。但因为运行性能差,没有被开发人员广泛使用,这里不展开讨论。