base64的實(shí)現(xiàn)原理
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
作者 | 請(qǐng)叫我宋某某
來(lái)源 | urlify.cn/qArEjq
base64是處理二進(jìn)制數(shù)據(jù)的一種編碼方式,可用于把二進(jìn)制數(shù)據(jù)編碼成64個(gè)可打印的字符。
學(xué)習(xí)base64之前,先了解一下什么是字節(jié)與編碼
什么是字節(jié)
互聯(lián)網(wǎng)中的數(shù)據(jù)都是用字節(jié)來(lái)表示的,一個(gè)字節(jié)有8位二進(jìn)制數(shù)據(jù)組成即00000000 -- 11111111
什么是編碼
編碼是把字符串轉(zhuǎn)化成二進(jìn)制數(shù)據(jù)的一種方式,計(jì)算機(jī)發(fā)展的過(guò)程中,最先定義了ASCII編碼,用于表示英文字符和一些英文字符為128個(gè)字符;后來(lái)隨著計(jì)算機(jī)被普及到各國(guó)ASCII的編碼已經(jīng)不能滿足于顯示各國(guó)語(yǔ)言的文字,所以說(shuō)后面發(fā)展出了GBK、UNICODE 、UTF8、UTF16等不同類(lèi)型的編碼,在utf8編碼中一個(gè)英文字符占用1個(gè)字節(jié),一個(gè)中文字符占用3個(gè)字節(jié)
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的實(shí)現(xiàn)
base64是,64代表的就是6位二進(jìn)制數(shù)據(jù),通過(guò)把字符串轉(zhuǎn)化為二進(jìn)制數(shù)據(jù),然后按照每6位二進(jìn)制數(shù)據(jù)來(lái)進(jìn)行分割再把這6位二進(jìn)制數(shù)據(jù)轉(zhuǎn)化為10進(jìn)制數(shù)找到對(duì)應(yīng)的映射表就可生成base64編碼
具體實(shí)現(xiàn)步驟如下:
字符串轉(zhuǎn)化為2進(jìn)制數(shù)據(jù)
2進(jìn)制數(shù)據(jù)按照每6位一組分割, 不足6位的補(bǔ)0
6位二進(jìn)制數(shù)據(jù)轉(zhuǎn)化為十進(jìn)制數(shù)
在對(duì)應(yīng)的base64映射表中找到對(duì)應(yīng)的映射字符,補(bǔ)0的每?jī)晌挥靡粋€(gè)=號(hào)表示
例子
以字符串'A'為例
首先轉(zhuǎn)為16進(jìn)制數(shù)據(jù)為
41對(duì)應(yīng)的二進(jìn)制數(shù)據(jù)為01000001每6位二進(jìn)制數(shù)據(jù)分割為一組結(jié)果為
010000 0100006位二進(jìn)制轉(zhuǎn)化為10進(jìn)制的結(jié)果為
16 16base64映射表對(duì)用的字符為
Q Q因?yàn)檠a(bǔ)了4個(gè)0所以字符串
A對(duì)用的base64編碼就為QQ==
代碼實(shí)現(xiàn)
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
}
結(jié)束語(yǔ)
雖然base64可以便于二進(jìn)制數(shù)據(jù)傳輸且不會(huì)造成亂碼;但是值得注意的是,由于base64的性質(zhì)(把8個(gè)字節(jié)轉(zhuǎn)化為6個(gè)字節(jié)儲(chǔ)存),所以不可避免的會(huì)把文件的大小增大1/3,所以base64也不可盲目使用


