# Base64是什么
Base64是最常见的用于传输8Bit字节码的编码方式之一,它是一种基于64个可打印字符来表示二进制数据的方法,它的作用是将任意二进制数据(如图片、音频、文本等)转换为只包含英文字母、数字、加号 + 和斜杠 / 的字符串,便于在网络上传输或嵌入到某些只支持 ASCII 的系统中
Base64 不是加密,也不是字符编码,它只是对字节流进行编码
Base64编码,是由64个字符组成编码集
- 26个大写字母A~Z
- 26个小写字母a~z
- 10个数字0~9
- 符号 "+" 与 符号 "/"
Base64编码的基本思路是将原始数据的3个字节拆分转化为4个字节,然后根据Base64的对应表,得到对应的编码数据。
当原始数据凑不够3字节时,编码结果中会使用额外的符号=来表示这种情况
# 编码特点
| 特点 | 说明 |
|---|---|
| 可逆 | Base64 编码是可解码的,不是加密 |
| 增大体积 | 编码后数据体积会增加约 33% |
| 安全性 | Base64 不是加密,数据可以被轻易解码 |
| 适用范围 | 适用于传输二进制数据、嵌入资源、邮件传输等 |
# 编码表
| 码值 | 字符 | 码值 | 字符 | 码值 | 字符 |
|---|---|---|---|---|---|
| 0 | A | 26 | a | 52 | 0 |
| 1 | B | 27 | b | 53 | 1 |
| 2 | C | 28 | c | 54 | 2 |
| 3 | D | 29 | d | 55 | 3 |
| 4 | E | 30 | e | 56 | 4 |
| 5 | F | 31 | f | 57 | 5 |
| 6 | G | 32 | g | 58 | 6 |
| 7 | H | 33 | h | 59 | 7 |
| 8 | I | 34 | i | 60 | 8 |
| 9 | J | 35 | j | 61 | 9 |
| 10 | K | 36 | k | 62 | + |
| 11 | L | 37 | l | 63 | / |
| 12 | M | 38 | m | ||
| 13 | N | 39 | n | ||
| 14 | O | 40 | o | ||
| 15 | P | 41 | p | ||
| 16 | Q | 42 | q | ||
| 17 | R | 43 | r | ||
| 18 | S | 44 | s | ||
| 19 | T | 45 | t | ||
| 20 | U | 46 | u | ||
| 21 | V | 47 | v | ||
| 22 | W | 48 | w | ||
| 23 | X | 49 | x | ||
| 24 | Y | 50 | y | ||
| 25 | Z | 51 | z |
# 核心思想
本质是将 3 字节(24位) 的二进制数据拆分成 4 组(每组6位),然后映射到一个预定义的字符表中,生成可打印的 ASCII 字符。
# 编码步骤
- 将原始数据(文本或二进制)转换为字节流(如 UTF-8)
- 把字节流转换为二进制字符串
- 再将这24个二进制位,每6个一划分,分为四组(6×4=24个二进制位)
- 计算每组的10进制数值,查询码表,转换为对应的Base64的字符即可
# 编码过程
以我爱Java为例
# 将 “我爱Java” 转换为 UTF-8 二进制表示方式
- 我 11100110 10001000 10010001
- 爱 11100111 10001000 10110001
- J 01001010
- a 01100001
- v 01110110
- a 01100001
合并所有二进制
11100110 10001000 10010001 11100111 10001000 10110001 01001010 01100001 01110110 01100001
这组二进制的UTF-8编码格式为E6 88 91 E7 88 B1 C2 B7 4A 61 76 61
具体参照UTF-8编码格式规则
# 每 6 位一组拆分(不足则补零)
111001 101000 100010 010001 111001 111000 100010 110001 010010 100110 000101 110110 011000 01
注意到最后一组数据只有2位,补0
111001 101000 100010 010001 111001 111000 100010 110001 010010 100110 000101 110110 011000 010000
# 转为十进制,映射字符
| 二进制 | 十进制 | base64映射字符 |
|---|---|---|
| 111001 | 57 | 5 |
| 101000 | 40 | o |
| 100010 | 34 | i |
| 010001 | 17 | R |
| 111001 | 57 | 5 |
| 111000 | 56 | 4 |
| 100010 | 34 | i |
| 110001 | 49 | x |
| 010010 | 18 | S |
| 100110 | 38 | m |
| 000101 | 5 | F |
| 110110 | 54 | 2 |
| 011000 | 24 | Y |
| 010000 | 16 | Q |
对应的base64编码 5oiR54ixSmF2YQ
# 填充 =
原始的二进制数据
11100110 10001000 10010001 11100111 10001000 10110001 01001010 01100001 01110110 01100001
总共有10个字节
10%3 = 1,所以,需要补充3-1=2个=
最终结果:
5oiR54ixSmF2YQ==
# 总结
| 原始内容 | UTF-8 字节流(Hex) | Base64 编码结果 |
|---|---|---|
| 我爱Java | E6 88 91 E7 88 B1 4A 61 76 61 | 5oiR54ixSmF2YQ== |
# 解码过程
以5oiR54ixSmF2YQ==为例
# 去除填充符号(如果有) =
变成5oiR54ixSmF2YQ
# 查询base64编码表,将字符还原为实际的码值
| base64映射字符 | 十进制 | 二进制 |
|---|---|---|
| 5 | 57 | 111001 |
| o | 40 | 101000 |
| i | 34 | 100010 |
| R | 17 | 010001 |
| 5 | 57 | 111001 |
| 4 | 56 | 111000 |
| i | 34 | 100010 |
| x | 49 | 110001 |
| S | 18 | 010010 |
| m | 38 | 100110 |
| F | 5 | 000101 |
| 2 | 54 | 110110 |
| Y | 24 | 011000 |
| Q | 16 | 010000 |
二进制编码格式为
111001 101000 100010 010001 111001 111000 100010 110001 010010 100110 000101 110110 011000 010000
# 每8位拆分
11100110 10001000 10010001 11100111 10001000 10110001 01001010 01100001 01110110 01100001 0000
最后多余的0000去掉
变成
11100110 10001000 10010001 11100111 10001000 10110001 01001010 01100001 01110110 01100001
# 按照UTF-8编码规则
把这组字二进制编码分为7组,分别是
- 11100110 10001000 10010001
- 11100111 10001000 10110001
- 11000010 10110111
- 01001010
- 01100001
- 01110110
- 01100001
接下来对每组分别还原
- 11100110 10001000 10010001 ,这是1个3字节符号,格式为1110xxxx 10xxxxxx 10xxxxxx,把这个格式中占位的 1 和 0 全部去掉,只留下 x。得到 0110 001000 010001,每4位一组
0110 0010 0001 0001,用16进制表示为6211,查询Unicode编码得知,码点U+6211代表汉字我 - 11100111 10001000 10110001 ,代表汉字
爱 - 11000010 10110111,代表符号
· - 01001010 表示字母
J - 01100001 表示字母
a - 01110110 表示字母
v - 01100001 表示字母
a
所以,还原结果为 我爱Java
← 编码转换