9. Illustrations and Examples (图示和示例)
为了在二进制和base编码之间进行转换,输入被存储在一个结构中,输出被提取出来。
Base64编码图示
以下是Base64的情况,该图借自 [5]:
输入: 3个八位字节
+--第1个八位字节-+-第2个八位字节-+--第3个八位字节-+
|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
+-----------+---+-------+-------+---+-----------+
|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|
+--1.索引--+--2.索引--+--3.索引--+--4.索引--+
输出: 4个字符
详细说明
输入的24位被重新分组为4个6位组:
位索引: 23 22 21 20 19 18 | 17 16 15 14 13 12 | 11 10 9 8 7 6 | 5 4 3 2 1 0
|----字符1----| |----字符2----| |---字符3---| |---字符4---|
Base32编码图示
以下是Base32的情况,该图借自 [7]。Base32值中的每个连续字符表示底层八位字节序列的5个连续位。因此,每组8个字符表示5个八位字节的序列(40位)。
输入: 5个八位字节 (40位)
1 2 3
01234567 89012345 67890123 45678901 23456789
+--------+--------+--------+--------+--------+
|< 1 >< 2| >< 3 ><|.4 >< 5.|>< 6 ><.|7 >< 8 >|
+--------+--------+--------+--------+--------+
<===> 第8个字符
<====> 第7个字符
<===> 第6个字符
<====> 第5个字符
<====> 第4个字符
<===> 第3个字符
<====> 第2个字符
<===> 第1个字符
详细说明
输入的40位被重新分组为8个5位组:
位索引: 39-35 | 34-30 | 29-25 | 24-20 | 19-15 | 14-10 | 9-5 | 4-0
字符1 字符2 字符3 字符4 字符5 字符6 字符7 字符8
Base64编码示例(带详细步骤)
以下Base64数据示例来自 [5],已更正。
示例1: 完整的3字节组
输入数据: 0x14fb9c03d97e
十六进制: 1 4 f b 9 c | 0 3 d 9 7 e
8位: 00010100 11111011 10011100 | 00000011 11011001 01111110
6位: 000101 001111 101110 011100 | 000000 111101 100101 111110
十进制: 5 15 46 28 0 61 37 62
输出: F P u c A 9 l +
示例2: 2字节输入(需要1个填充)
输入数据: 0x14fb9c03d9
十六进制: 1 4 f b 9 c | 0 3 d 9
8位: 00010100 11111011 10011100 | 00000011 11011001
用00填充 ↓
6位: 000101 001111 101110 011100 | 000000 111101 100100
十进制: 5 15 46 28 0 61 36
用=填充 ↓
输出: F P u c A 9 k =
示例3: 1字节输入(需要2个填充)
输入数据: 0x14fb9c03
十六进制: 1 4 f b 9 c | 0 3
8位: 00010100 11111011 10011100 | 00000011
用0000填充 ↓
6位: 000101 001111 101110 011100 | 000000 110000
十进制: 5 15 46 28 0 48
用=填充 ↓ ↓
输出: F P u c A w = =
编码过程可视化
Base64编码过程
步骤1: 输入分组
输入: [Byte1] [Byte2] [Byte3]
8位 8位 8位
↓
24位总计
步骤2: 重新分组
[6位] [6位] [6位] [6位]
↓ ↓ ↓ ↓
索引1 索引2 索引3 索引4
步骤3: 查表转换
索引 → 字符
↓ ↓
输出: [Char1][Char2][Char3][Char4]
Base32编码过程
步骤1: 输入分组
输入: [Byte1][Byte2][Byte3][Byte4][Byte5]
8位 8位 8位 8位 8位
↓
40位总计
步骤2: 重新分组
[5位][5位][5位][5位][5位][5位][5位][5位]
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
索引1 索引2 索引3 索引4 索引5 索引6 索引7 索引8
步骤3: 查表转换
索引 → 字符
↓ ↓
输出: [C1][C2][C3][C4][C5][C6][C7][C8]
填充示例对比
Base64填充
| 输入字节数 | 输出字符 | 填充 | 说明 |
|---|---|---|---|
| 3 | XXXX | 无 | 完整组 |
| 2 | XXX= | 1个= | 缺1字节 |
| 1 | XX== | 2个= | 缺2字节 |
Base32填充
| 输入字节数 | 输出字符 | 填充 | 说明 |
|---|---|---|---|
| 5 | XXXXXXXX | 无 | 完整组 |
| 4 | XXXXXXX= | 1个= | 缺1字节 |
| 3 | XXXXX=== | 3个= | 缺2字节 |
| 2 | XXXX==== | 4个= | 缺3字节 |
| 1 | XX====== | 6个= | 缺4字节 |
实际转换示例
文本编码
输入: "Hello"
ASCII码: H=72, e=101, l=108, l=108, o=111
十六进制: 0x48 0x65 0x6C 0x6C 0x6F
Base64:
01001000 01100101 01101100 → SGVs
01101100 01101111 [补零] → bG8=
输出: "SGVsbG8="
Base32:
01001000 01100101 01101100 01101100 01101111
→ "JBSWY3DP"
Base16:
→ "48656C6C6F"
二进制数据编码
输入: [0xFF, 0x00, 0xAA]
二进制: 11111111 00000000 10101010
Base64:
111111 110000 000010 101010
63 48 2 42
/ w C q
输出: "/wCq"
Base32:
11111 11100 00000 01010 10100
31 28 0 10 20
7 4 A K U
输出: "74AKU==="
Base16:
输出: "FF00AA"
边界情况示例
空输入
输入: "" (0字节)
Base64: ""
Base32: ""
Base16: ""
所有编码都返回空字符串
单字节
输入: [0x00]
Base64: "AA=="
Base32: "AA======"
Base16: "00"
全0字节
输入: [0x00, 0x00, 0x00]
Base64: "AAAA"
Base32: "AAAAAAAA"
Base16: "000000"
全1字节
输入: [0xFF, 0xFF, 0xFF]
Base64: "////"
Base32: "77777777"
Base16: "FFFFFF"
编码效率对比
原始数据: 100字节
Base64:
输出: 136字节
效率: 100/136 ≈ 73.5%
膨胀: +36%
Base32:
输出: 160字节
效率: 100/160 = 62.5%
膨胀: +60%
Base16:
输出: 200字节
效率: 100/200 = 50%
膨胀: +100%
实用技巧
快速估算输出长度
Base64:
输出字符数 ≈ (输入字节数 × 4 / 3) 向上取整到4的倍数
Base32:
输出字符数 ≈ (输入字节数 × 8 / 5) 向上取整到8的倍数
Base16:
输出字符数 = 输入字节数 × 2
填充检测
Base64:
无填充: 字符数是4的倍数
1个=: 原始数据模3余2
2个=: 原始数据模3余1
Base32:
无填充: 字符数是8的倍数
根据填充数量可推导原始长度
调试技巧
手工验证
1. 选择简单输入
示例: "A" (0x41)
2. 转换为二进制
0x41 = 01000001
3. 按位分组
Base64: 010000 01[0000]
Base32: 01000 001[00]
4. 查表验证
Base64: Q Q (+ 填充)
Base32: I E (+ 填充)
常见错误诊断
错误输出特征:
❌ 长度不正确 → 检查填充逻辑
❌ 乱码字符 → 检查字母表
❌ 解码失败 → 验证输入有效性
这些示例和图示帮助理解Base编码的内部工作原理,对于实现和调试都非常有用。