base64的实现原理
点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
作者 | 请叫我宋某某
来源 | urlify.cn/qArEjq
base64是处理二进制数据的一种编码方式,可用于把二进制数据编码成64个可打印的字符。
学习base64之前,先了解一下什么是字节与编码
什么是字节
互联网中的数据都是用字节来表示的,一个字节有8位二进制数据组成即00000000 -- 11111111
什么是编码
编码是把字符串转化成二进制数据的一种方式,计算机发展的过程中,最先定义了ASCII编码,用于表示英文字符和一些英文字符为128个字符;后来随着计算机被普及到各国ASCII的编码已经不能满足于显示各国语言的文字,所以说后面发展出了GBK、UNICODE 、UTF8、UTF16等不同类型的编码,在utf8编码中一个英文字符占用1个字节,一个中文字符占用3个字节
base64编码表
码值 | 字符 | 码值 | 字符 | 码值 | 字符 | 码值 | 字符 |
---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w |
1 | B | 17 | R | 33 | h | 49 | x |
2 | C | 18 | S | 34 | i | 50 | y |
3 | D | 19 | T | 35 | j | 51 | z |
4 | E | 20 | U | 36 | k | 52 | 0 |
5 | F | 21 | V | 37 | l | 53 | 1 |
6 | G | 22 | W | 38 | m | 54 | 2 |
7 | H | 23 | X | 39 | n | 55 | 3 |
8 | I | 24 | Y | 40 | o | 56 | 4 |
9 | J | 25 | Z | 41 | p | 57 | 5 |
10 | K | 26 | a | 42 | q | 58 | 6 |
11 | L | 27 | b | 43 | r | 59 | 7 |
12 | M | 28 | c | 44 | s | 60 | 8 |
13 | N | 29 | d | 45 | t | 61 | 9 |
14 | O | 30 | e | 46 | u | 62 | + |
15 | P | 31 | f | 47 | v | 63 | / |
base64的实现
base64是,64代表的就是6位二进制数据,通过把字符串转化为二进制数据,然后按照每6位二进制数据来进行分割再把这6位二进制数据转化为10进制数找到对应的映射表就可生成base64编码
具体实现步骤如下:
字符串转化为2进制数据
2进制数据按照每6位一组分割, 不足6位的补0
6位二进制数据转化为十进制数
在对应的base64映射表中找到对应的映射字符,补0的每两位用一个=号表示
例子
以字符串'A'
为例
首先转为16进制数据为
41
对应的二进制数据为01000001
每6位二进制数据分割为一组结果为
010000 010000
6位二进制转化为10进制的结果为
16 16
base64映射表对用的字符为
Q Q
因为补了4个0所以字符串
A
对用的base64编码就为QQ==
代码实现
function addZero2Front(str) {
let len = str.length
while (len < 8) {
str = '0' + str
len++
}
return str
}
function getBinary(str) {
const buf = Buffer.from(str)
let binary = ''
for (let i = 0; i < buf.length; i++) {
binary += addZero2Front(
buf[i].toString(2)
)
}
return binary
}
let map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
function base64(str) {
let binary = getBinary(str)
let num = binary.length % 6
let needAddZeroLen = num !== 0 ? 6 - num : num
let i = needAddZeroLen;
let endStr = ''
let res = ''
while (i > 0) {
binary += '0'
i--
}
i = needAddZeroLen
while ( i > 0) {
endStr += '='
i -= 2
}
i = 0
while (i < binary.length) {
let idx = parseInt(
binary.slice(i, i + 6),
2
)
res += map[idx]
i+=6
}
res += endStr
return res
}
结束语
虽然base64可以便于二进制数据传输且不会造成乱码;但是值得注意的是,由于base64的性质(把8个字节转化为6个字节储存),所以不可避免的会把文件的大小增大1/3,所以base64也不可盲目使用