黄山的冬天,中国 (© Hung Chung Chih/Shutterstock)
Base64
前端的日常开发中可能会接触到 Base64 ,比如页面上的小图片,在为了节省网络资源的情况下,通常会将图片转为 Base64 直接嵌入到 html 或者 css 里。这里,我们先来看看 Base64 是什么,以及 Base64 编码做了什么。
什么是 Base64
Base64 是一种基于64个可打印字符来表示二进制数据的表示方法。一般来说,64个字符包括 A-Z,a-z,0-9 以及 +/ 两个字符(via)。换句话说, Base64 可以将二进制数据转换为这 64 个字符来表示,数据来源可以是图片,也可以是任意的字符串。
Base64 做了些什么
上面提到了 Base64 做的其实就是将二进制数据按照对应规则进行转化,转化的流程其实也很简单
- 得到一份二进制数据
- 将二进制数据 6位 一组进行划分,并进行适当的补位
- 按照 Base64 索引表,将每组数据转换为 Base64 索引表对应的字符,补位位置用 =
下面我们来尝试一下将 aa 这个字符串进行一下 Base64 编码:
第一步:通过 ASCII 表将 aa 转换为对应的二进制表示
可知 a 在 ASCII 表对应的二进制表示为 0110 0001,则 aa 对应为 0110 0001 0110 0001
注:
- ascii 参考
- 中文等其他字符参考其他表(UTF-8)进行转换即可
第二步:数据分组和补位
按 6 位一组划分后 011000 010110 0001,我们发现数据还少两位,所以我们需要按规则对数据进行补位,补一字节(8位),二进制数据变为 0110 0001 0110 0001 0000 0000,划分为 011000 010110 000100 000000
第三步:查 Base64 索引表 进行转换
参考一张常用的索引表 可知 aa = 011000 010110 000100 000000 对应为 011000(Y ) 010110(W ) 000100(E ) 000000(补位= ) 即 YWE=,我们就得到了 aa 的 Base64 编码为 YWE= ,是不是挺简单。
Base62
说完了 Base64,我们再来聊聊 Base62。在通过 url 传递数据的场景下,通过 Base64 进行编码的数据会带来问题(Base64 中的 / 等可能会带来路径的解析异常),所以在 Base62 里,去掉了 +/= 字符。 说到这里,大家可能觉得就讲完了,Base62 就是丢掉了几个不安全的字符而已,其余转换方法和 Base64 一样,我起初也是这么认为的。
不一样的 Base62 结果
当我尝试对 aa 进行 Base62 编码时,按推算好像也不太对? = 补位已经被去掉了,怎么来做实现呢? 在我找了几个 online 转换进行测试后,发现 aa 对应的 Base62 编码为 6U5 看着跟 Base64 毫无关系对吧,实际上也是的。
揭开面纱看看
查了几份资料以及现有的仓库实现后,我发现 Base62 编码的流程是这样的:
- 获得一份二进制数据
- 二进制数据 转 10进制
- 10进制 转 62进制(按索引表)
我们再来试试将 aa 转 Base62:
第一步:转二进制
aa 对应 0110 0001 0110 0001
第二步:转10进制
0110000101100001 对应十进制为 24929
第三步:转62进制(参考索引表)
24929 = 6622+30 62+5
按表可知,6=6 30=U 5=5,即 6U5
注:
- 索引表可以自行更换,并不一定是上图顺序
- 现有的仓库实现里,部分只实现了 10进制 转 62进制( base62/base62.js),有的实现了更完整的转换 ( tuupola/base62)
分析一下原因
说实话我查到的资料不多,但是根据 en.wikipedia.org/wiki/Talk:B... 猜测,文里提到 Base64 后的数据会膨胀到 133% 。Base62 还存在对数据进行压缩的改进,所以采用了这样与 Base64 差别有点大的方式来设计。
总结一下
文章简单的谈了谈 Base64 是什么,怎么实现以及 Base62 的实现,并分析了一下 Base62 设计的初衷,整体来说还是挺简单,希望对你有所帮助 :)