Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法。由于 log 2 64 = 6 \log_{2}64=6 log264=6,所以每 6 比特为一个单元,对应某个可打印字符。
3 个字节相当于 24 个比特,对应于 4 个 Base64 单元,即 3 个字节可由 4 个可打印字符来表示。在 Base64 中的可打印字符包括字母 A-Z、a-z、数字 0-9,这样共有 62 个字符,此外两个可打印符号在不同的系统中而不同。
一些如 uuencode 的其他编码方法,和之后 BinHex 的版本使用不同的 64 字符集来代表 6 个二进制数字,但是不被称为 Base64。
以上是维基百科对 Base64 的描述。也就是说 Base64 是一种二进制到文本的编码方式,而且该文本只包含 ASCII 的可见字符。
数值 | 字符 | 数值 | 字符 | 数值 | 字符 | 数值 | 字符 |
---|---|---|---|---|---|---|---|
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 | / |
如上图所示,字符串 hello
经过 Base64 编码则生成 aGVsbG8=
,ASCII 字符不足则 Base64 用 0 比特补足,若 Base64 单元不为 4 的倍数也用 0 比特补足,但展示为 =
, 表示为填充位。
对应 Java 代码为:
// JDK 17 var arr = "hello".getBytes(StandardCharsets.UTF_8); var ints = new ArrayList<Integer>(arr.length); for (byte b : arr) { ints.add(b & 0xFF); } ints.stream() .map(b -> Integer.toBinaryString(b & 0xFF)) .map(s -> String.format("%8s", s).replace(' ', '0')) .forEach(System.out::println); var base64 = Base64.getEncoder().encodeToString(arr); System.out.println(base64);
输出如下:
01101000 01100101 01101100 01101100 01101111 aGVsbG8=
从 Base64 的定义中我们可以知道,Base64 把所有不可见字符都转为可见字符了,那么 Base64 主要也就是处理文本协议在传输过程中不可见字符的问题了。在网络交换数据的时候,数据需要经过多个路由设备,由于不同设备处理对不可见字符处理的不同,可能出现错误的处理,这是不利于传输的,于是乎就出现 Base64 这样的编码方式。