Base64 编码实践

228 阅读3分钟

前言

Hello 大家好!我是壹甲壹!

在开发中,都使用过 Base64 对小图片进行编码成 data:image/png;base64, xxx... 格式的字符串,优势在于减少请求。

而今天要探讨的是为什么叫 Base64 编码而不叫 Base32 ? 64 是从何而来的?

编码发展史

探究 Base64 如何编码之前,先了解下编码发展史。

1.1 ASCII

ASCII 码由美国人发明,一个字节用来描述一个字符,一共定义了 128 个字符。 不足:只能用于显示现代英语和其他西欧语言

1.2 GBK

对于如何显示汉字,中国在 ASCII 的基础上,扩展出 gb2312, 再到 gbk ,最后到 gb18030

同时规定 两个字节描述一个汉字

1.3 Unicode

每个国家都在 ASCII 进行各自的编码扩展,而 Unicode 的出现为每种语言中的每个字符设定了统一并且唯一的二进制编码,Unicode 也被成为 万国码统一码

而常见的 UTF-8 是针对Unicode的一种可变长度字符编码,也有 UTF-16, UTF-32

UTF-8 中规定,三个字节描述一个汉字

Base64编码实践

以汉字 为例,默认 utf8 格式,那么就是 3个字节一共 24 位。

1、使用 Buffer.from("甲") 输出汉字的 16 进制表示

Buffer.from("甲")
// <Buffer e7 94 b2>

2、将其每个字节转换成 二进制

console.log((0xe7).toString(2))
console.log((0x94).toString(2))
console.log((0xb2).toString(2))

// 11100111 10010100 10110010

3、按照规定,将 24 位变成 4 个字节,每个字节不够 8 位的前置补零

111001111001010010110010
// 拆成4个字节
111001 111001 010010 110010
// 前置补零
00111001 00111001 00010010 00110010

4、转换成 4 个字节后,每个字节的前 2 位都是 0 ,所以取值范围是 00000000 ~ 00111111 ,后 6 位正好 是0~2^6-1 , 一共 64 个,所以才会叫 Base64

5、将二进制的 4 个字节转换成 10 进制,

console.log(parseInt("00111001", 2))
console.log(parseInt("00111001", 2))
console.log(parseInt("00010010", 2))
console.log(parseInt("00110010", 2))

// 57 57 18 50

6、Base64 存在一个取值表

let str = `ABCDEFGHIGKLMNOPQRSTUVWXYZ`
str += str.toLocaleLowerCase()
str += '0123456789+/'

7、从取值表中找出 57 57 18 50 几位对应的字符了

str[57] + str[57] + str[18] + str[50]
"55Sy"

8、我们使用在线工具 Base64 解码55Sy 解码输出的正好是汉字

总结

  • Base64 会将一个汉字由 3 个字节转成 4 个字节,所以转换后体积变大 1/3
  • 大文件并不适合 Base64 编码
  • 不同文件有着不同的 Base64 编码风格(对照表), 图片有字节的规则表,不够位会进行补等于号。
截屏2020-07-11下午3.30.42.png
截屏2020-07-11下午3.30.42.png

本文使用 mdnice 排版