为什么base64编码要用=做对齐
首先明确一下问题,重点在“为什么做对齐”,而不是“为什么用=这个符号”。
先解释一下对齐操作。
base64编码的输入是字节串,每个字节8比特;输出是64进制串的文本,每个单元为6比特。如果输入长度是3的倍数,那么输出是不需要对齐的:
0 1 1 0 1 0 1 1/1 0 0 0 0 1 0 1/0 0 0 1 1 1 1 1 0 1 1 0 1 0/1 1 1 0 0 0/0 1 0 1 0 0/0 1 1 1 1 1
3个字节恰好被拆成了4个base64码。
但是如果输入长度不是3的倍数,那么就需要特殊处理了:
1、剩余长度为2字节
0 1 1 0 1 0 1 1/1 0 0 0 0 1 0 1 0 1 1 0 1 0/1 1 1 0 0 0/0 1 0 1 0 0/=
一是将第三个base64码的后两个比特填充0。另外,base64编码再最后对齐一个=等号,作为一个特殊的base64字符,表示空。
2、剩余长度为1字节
0 1 1 0 1 0 1 1 0 1 1 0 1 0/1 1 0 0 0 0/=/=
和前者类似,但是会对齐两个=等号。
经过等号对齐后,base64编码的长度就始终为4的倍数了。
但是,从编码解码原理上看,不对齐=也是没问题的,也不会造成二义性:
将base64编码视为每4个一组,
1)当最后一组长度为3时,说明是2个字节
2)当最后一组长度为2时,说明是1个字节
3)当最后一组长度为1时,不合法
解码时根据情况舍弃后面填充的0,转换为原字节,这个方案是完全没问题的。
那既然不对齐=也能正常工作,为什么要对齐呢?
考虑两个base64串的拼接:
0 1 1 0 1 0 1 1/1 0 0 0 0 1 0 1 0 1 1 0 1 0/1 1 1 0 0 0/0 1 0 1 0 0
+
0 1 1 0 1 0 1 1/1 0 0 0 0 1 0 1/0 0 0 1 1 1 1 1 0 1 1 0 1 0/1 1 1 0 0 0/0 1 0 1 0 0/0 1 1 1 1 1
如果对齐=,那么两个base64编码可以直接拼起来:
0 1 1 0 1 0 1 1/1 0 0 0 0 1 0 1/ /0 1 1 0 1 0 1 1/1 0 0 0 0 1 0 1/0 1 0 0 1 1 1 1 0 1 1 0 1 0/1 1 1 0 0 0/0 1 0 1 0 0/= /0 1 1 0 1 0/1 1 1 0 0 0/0 1 0 1 0 1/0 0 1 1 1 1
解码时遇到=就知道那里没数据,做些特殊处理直接跳过。
而如果没有=对齐,就很麻烦了:
0 1 1 0 1 0 1 1/1 0 0 0 0 1 0 1/0 1 1 0 1 0 1 1/1 0 0 0 0 1 0 1/0 1 0 0 1 1 1 1
0 1 1 0 1 0/1 1 1 0 0 0/0 1 0 1 0 1/1 0 1 0 1 1/1 0 0 0 0 1/0 1 0 1 0 0/1 1 1 1 0 0
注意标红的比特,左串的最后一个base64码,和右串的所有base64码都需要被改写!
因此,对齐机制至少有支持拼接这一好处,即使会稍微浪费一点空间。