引出
众所周知, ASICC编码共127个, 使用了7个bit进行编码. 而文件在存储的时候是以 字节为单位, 也就是8bit. 这就难免导致有一部分编码是没有定义在ASICC编码中的.
而在网络中传输二进制数据的时候(字符串本质上也是二进制数据嘛), 如果直接传输比特流, 倒也不是不可以, 只是肉眼难以识别造成不便. 比如你在调试HTTP接口的时候, 对面传输的是一段字符串, 你抓包看到的都是一堆方块, 什么心情. 而且一些特殊的编码会影响对数据的解析, 造成解析错误.
而ASICC编码是最通用的, 故而需要有一种机制, 能够将二进制数据转换为可见的ASICC编码字符串进行传输, 等到需要的时候, 再通过解码原封不动的转回去. 而这, 就是base64编码了.
实施
如何做到将二进制数据转换为可见的ASICC编码字符串呢?
选出可见字符
首先, 要先选出使用的可见ASICC编码, 从base64的名字也能看的出来, 一共选了64个, 分别是:
a-z A-Z 0-9 + /
好, 现在已经将使用的64个可见字符选出来了, 可以进行编码转换了.
64个字符一一映射后可编码6bit, 其编码映射表如下:

也就是说, 原内容的6bit, 编码后为8bit. 没错, 会增加内容的大小.
编码步骤
我们尝试着对字符串hjn进行编码.
通过查询ASICC 编码表将其转为二进制:
01101000 01101010 01101110 共3个字节.
然后将其拆分为每6bit 一组:
011010 000110 101001 101110
将上方的6bit 二进制按照映射表进行转换, 结果为: aGpu. 使用PHP进行验证后, 结果与我们计算的一致.
<?php
// aGpu
echo base64_encode('hjn'), PHP_EOL;
补全码
我们再尝试对hj进行编码. 其二进制内容为: 01101000 01101010
按照6bit 分组后发现最后一组不足6bit, 就在后面补0: 011010 000110 101000
映射后, 其结果为: aGo. 但是, base64规定其必须是4字节一组, 当不足4字节时向后面添加补全码进行对其. 这个补全码就是=
因此, hj的base64编码为aGo=. 同理, 若仅对h进行编码, 则结果为aA==
那么, 当对aGo=解码的时候, 将后面的补全码=去掉, 解码后为: 011010 000110 101000. 如何能够确定后面的两个00需要去掉呢? 很简单, 存储的时候以字节为单位, 当末尾剩余00不足1字节时, 说明是编码时额外加上的, 可以去掉.
应用场景
齐了, base64编码就这么点东西. 它可以应用到下列场景(暂时想到):
- 网页显示图片, 使用base64编码图片
- 数据中存在特殊符号, 影响解析, 使用base64将其编码为普通符号
- xml 中的 value 存在
</xml>结束符号, 影响内容解析 - 传输过程中, 字符串中存在
\n换行符, 影响单行内容传输 - 等等
- xml 中的 value 存在
- 等等吧
对了, 上面介绍了base64编码. 相对应的base32 base16编码原理均相同, 只是编码时使用的位数不同而已.