引出
众所周知, 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
编码原理均相同, 只是编码时使用的位数不同而已.
原文地址: https://hujingnb.com/archives/760