Base64 是一种用 64 个可打印字符来表示二进制数据的方法。它之所以被创造出来,是因为很多网络传输协议(如电子邮件 SMTP)是设计用来传输文本的,对于二进制数据(如图片、文件等)中的控制字符(如NULL,换行符)处理得不好。Base64 将这些二进制数据“翻译”成纯文本字符,从而确保数据在传输过程中完整、不出错。
1. 核心原理
Base64 的核心思想是 将 3 个 8 位的字节(共 24 位)转换为 4 个 6 位的字节(也是 24 位),然后根据一个索引表,将这 4 个 6 位的数据映射为 4 个可打印的 ASCII 字符。
6位的数据可以表示64(2^6=64)个不同的字符,所以Base64编码后的数据长度会增加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 | / | 
填充字符是 =。
2. 编码过程(Encode)
2.1. 正常Case
我们以字符串 "Man" 为例,它的 ASCII 码二进制表示是:
1  | M = 77 (01001101)  | 
连起来是:01001101 01100001 01101110
步骤 1: 按 6 位分组
将这 24 位数据按每 6 位一组分开:
1  | 010011 010110 000101 101110  | 
步骤 2: 转换为十进制
将每组 6 位二进制数转换为十进制:
1  | 010011 -> 19  | 
步骤 3: 查表映射
根据 Base64 索引表,找到对应的字符:
1  | 19 -> T  | 
所以,"Man" 的 Base64 编码结果是 "TWFu"。
2.2. 处理字节数不是3的倍数的情况
如果原始数据的字节数不是 3 的倍数,编码过程会稍有不同,并在末尾使用 = 进行填充。
如两个字节 “Ma”:
1  | M = 77 (01001101)  | 
连起来是:01001101 01100001,一共 16 位。
步骤 1: 按 6 位分组(并在末尾补 0):
16 位不是 6 的倍数,我们在末尾补两个 0,凑成 18 位(3 个 6 位组):010011 010110 000100 (注意最后 4 位 0001 变成了 000100)
步骤 2: 转换为十进制:
1  | 010011 -> 19  | 
步骤 3: 查表映射:
1  | 19 -> T  | 
步骤 4: 填充:
因为我们原始数据只有 2 个字节(本应处理 3 个字节),所以需要在编码结果后加 一个 =。
最终结果:"TWE="
3. 解码过程(Decode)
解码是编码的逆过程。
- 去掉末尾的填充符 
=(如果有的话)。 - 将每个 Base64 字符根据索引表转换回对应的 6 位二进制值。
 - 将所有 6 位二进制值连接起来。
 - 每 8 位一组,转换回原始的字节数据。在编码时填充的 0 位会在这一步被自然地忽略掉。
 
以 "TWE=" 为例:
- 去掉 
=,剩下"TWE"。 - 查表:
- T -> 19 -> 
010011 - W -> 22 -> 
010110 - E -> 4 -> 
000100 
 - T -> 19 -> 
 - 连接起来:
010011 010110 000100->01001101 01100001 000100??
(最后 4 位0100是补的 0,实际有效数据是前面的01,加上前面的01100001,正好是a的 ASCII 码) - 按 8 位分组:
01001101-> 77 -> ‘M’01100001-> 97 -> ‘a’
(最后一个字节000100??因为原始数据只有 2 个字节,所以被丢弃)
解码结果为"Ma"。
 
4. 在编程中的使用
几乎所有现代编程语言都内置了 Base64 编解码的支持。
4.1. Python
1  | import base64  | 
4.2. JavaScript
1  | // 编码  | 
4.3. Java
1  | import java.util.Base64;  | 
5. 总结
- 目的:将二进制数据安全地转换为纯文本,用于不支持二进制数据的传输环境。
 - 原理:将每 3 个字节(24 位)的数据重新划分为 4 个 6 位的单元,每个单元映射到一个 Base64 索引表中的可打印字符。
 - 填充:如果原始数据字节数不是 3 的倍数,在编码结果末尾用 
=填充。 - 应用:电子邮件附件、在 HTML 中嵌入图片(Data URLs)、在 XML/JSON 中传输二进制数据等。