你真的懂 Base64 吗?短链服务常用的 Base62 呢?


黄山的冬天,中国 (© 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 做的其实就是将二进制数据按照对应规则进行转化,转化的流程其实也很简单

  1. 得到一份二进制数据
  2. 将二进制数据 6位 一组进行划分,并进行适当的补位
  3. 按照 Base64 索引表,将每组数据转换为 Base64 索引表对应的字符,补位位置用 =

下面我们来尝试一下将 aa 这个字符串进行一下 Base64 编码:

第一步:通过 ASCII 表将 aa 转换为对应的二进制表示

可知 a 在 ASCII 表对应的二进制表示为 0110 0001,则 aa 对应为 0110 0001 0110 0001
注:

  1. ascii 参考
  2. 中文等其他字符参考其他表(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 编码的流程是这样的:

  1. 获得一份二进制数据
  2. 二进制数据 转 10进制
  3. 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

注:

  1. 索引表可以自行更换,并不一定是上图顺序
  2. 现有的仓库实现里,部分只实现了 10进制 转 62进制( base62/base62.js),有的实现了更完整的转换 ( tuupola/base62

分析一下原因

说实话我查到的资料不多,但是根据 en.wikipedia.org/wiki/Talk:B... 猜测,文里提到 Base64 后的数据会膨胀到 133% 。Base62 还存在对数据进行压缩的改进,所以采用了这样与 Base64 差别有点大的方式来设计。

总结一下

文章简单的谈了谈 Base64 是什么,怎么实现以及 Base62 的实现,并分析了一下 Base62 设计的初衷,整体来说还是挺简单,希望对你有所帮助 :)

相关推荐
会豪几秒前
工业仿真(simulation)--前端(二)-资源管理器
前端
在未来等你8 分钟前
Elasticsearch面试精讲 Day 12:数据建模与字段类型选择
大数据·分布式·elasticsearch·搜索引擎·面试
a5876937 分钟前
消息队列(MQ)初级入门:详解RabbitMQ与Kafka
java·分布式·microsoft·面试·kafka·rabbitmq
@小红花1 小时前
从0到1学习Vue框架Day03
前端·javascript·vue.js·学习·ecmascript
前端与小赵1 小时前
vue3中 ref() 和 reactive() 的区别
前端·javascript·vue.js
魔云连洲1 小时前
Vue的响应式底层原理:Proxy vs defineProperty
前端·javascript·vue.js
专注VB编程开发20年1 小时前
CSS定义网格的列模板grid-template-columns什么意思,为什么要用这么复杂的单词
前端·css
IT_陈寒1 小时前
Redis性能提升50%的7个关键优化策略,90%开发者都不知道第5点!
前端·人工智能·后端
Hilaku1 小时前
深入URL和URLSearchParams:别再用正则表达式去折磨URL了
前端·javascript·代码规范
pubuzhixing1 小时前
Canvas 的性能卓越,用它解决一个棘手问题
前端