首页 > 技术文章 > base64的实现原理

songbw 2021-07-03 17:58 原文

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编码

具体实现步骤如下:

  1. 字符串转化为2进制数据
  2. 2进制数据按照每6位一组分割, 不足6位的补0
  3. 6位二进制数据转化为十进制数
  4. 在对应的base64映射表中找到对应的映射字符,补0的每两位用一个=号表示

例子

以字符串'A'为例

  1. 首先转为16进制数据为41对应的二进制数据为01000001
  2. 每6位二进制数据分割为一组结果为010000 010000
  3. 6位二进制转化为10进制的结果为16 16
  4. base64映射表对用的字符为Q Q
  5. 因为补了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也不可盲目使用

推荐阅读