Base64 vs Hex 编码:何时用哪个?数据密度与可读性的权衡
把二进制数据用文本表示,Base64 和 Hex 是两个最常见的选择。它们都能做到这件事,但密度、可读性和典型场景差异显著。选错通常不致命,但会增加存储成本、调试难度或 URL 长度。
这篇指南对比两者的内部机制、性能特征和典型使用场景。想自己动手编码解码两种格式?打开 Base64 编解码工具:点击编码后输出下方会显示同一字节的 Hex 对照,也可用 Hex → Base64 粘贴带 0x / 冒号 / 空格的十六进制,在同一页对比密度。
基本原理
Hex(十六进制):每个字节用两个十六进制字符表示(0-9, a-f)。一个字节的 256 个值映射到这两个字符的组合。
字节 0x48 → "48"
字节 0x65 → "65"
字节 0xFF → "ff"
Base64:每 3 个字节用 4 个 Base64 字符表示(A-Z, a-z, 0-9, +, /)。每个字符承载 6 位数据。
3 字节 = 24 位 → 4 个 6 位字符
这就是密度差异的来源:Hex 每字符承载 4 位,Base64 每字符承载 6 位。
密度对比
| 编码 | 字符数 / 字节 | 体积开销 | 字符集大小 |
|---|---|---|---|
| Hex | 2.0 | 100% | 16 |
| Base64 | ~1.33 | 33% | 64 |
同样 1 KB 的二进制数据:
- Hex 编码后:2 KB
- Base64 编码后:约 1.33 KB
差距在数据量大时显著。100 MB 文件 Hex 化是 200 MB,Base64 化只有 133 MB。
实战对比:编码 "Hello"
5 字节字符串 "Hello",看两种编码的实际输出:
import base64
data = b"Hello"
# Hex 编码
hex_encoded = data.hex()
# "48656c6c6f" (10 个字符)
# Base64 编码
b64_encoded = base64.b64encode(data).decode()
# "SGVsbG8=" (8 个字符,含 1 个填充 =)
# 字节对比
print(f"原始: {len(data)} 字节") # 5
print(f"Hex: {len(hex_encoded)} 字符") # 10
print(f"Base64: {len(b64_encoded)} 字符") # 8
注意 Base64 的 = 填充。Base64 把输入按 3 字节分组,"Hello" 是 5 字节(一组 3 + 一组 2),第二组只有 2 字节,编码后要补 1 个 = 让总长度是 4 的倍数。
Hex 的优势
1. 可读性强
每个字节单独可读,字节边界清晰。调试二进制协议时这个特性至关重要:
# Hex:能直接看出第 3 个字节是 0x6c
48 65 6c 6c 6f
# Base64:字节边界被 6 位分组打乱
SGVsbG8=
2. 大小写不敏感(实现上)
很多系统接受大写或小写 hex,简化了格式约定。Base64 严格区分大小写。
3. 易于手动构造
颜色代码、MAC 地址、内存地址这些短数据,hex 是天然选择:
# 颜色代码是 hex
#FFFFFF # 纯白
#FF0000 # 纯红
# MAC 地址用 hex 分隔
01:23:45:67:89:ab
# 内存地址
0x7ffeefbff5c8
4. 哈希摘要的标准表示
SHA-256、MD5 等哈希输出几乎总是用 hex 表示:
# SHA-256 输出是 32 字节,显示为 64 个 hex 字符
echo -n "hello" | shasum -a 256
# 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
用 Base64 表示 SHA-256 会更紧凑(44 字符 vs 64 字符),但业界惯例是 hex,工具链都按 hex 设计。
Base64 的优势
1. 紧凑
33% vs 100% 的体积差异。在大数据场景下显著。
2. URL 安全变体
标准 Base64 用 + 和 /,URL 里需要转义。Base64URL 用 - 和 _ 替代,可以直接放 URL:
import base64
# 标准 Base64(不适合 URL)
standard = base64.b64encode(b"\xfb\xff") # b'+/8='
# Base64URL(URL 安全)
urlsafe = base64.urlsafe_b64encode(b"\xfb\xff") # b'-_8='
3. 适合嵌入文本格式
JSON、XML、HTML 这些文本格式无法直接存二进制。Base64 把二进制塞进文本字段:
{
"image": "data:image/png;base64,iVBORw0KGgo..."
}
4. 多字节字符友好
Hex 编码 UTF-8 字符串时,每个字节单独编码,结果看不出原文结构。Base64 编码整段字节流,结果更紧凑。
何时用 Hex
- 哈希摘要:SHA-256、MD5、HMAC 的标准表示
- 加密密钥和 IV:调试时手动对比很方便
- 二进制协议调试:网络协议、文件格式、序列化数据
- 短二进制数据:颜色代码、MAC 地址、UUID、内存地址
- 加密货币和区块链:地址、交易哈希、区块哈希
何时用 Base64
- 数据 URI:图片、字体内嵌到 HTML 或 CSS
- JWT:token 的三段都是 Base64URL
- 电子邮件附件:MIME 标准用 Base64 编码二进制附件
- 大体积二进制:节省存储或传输成本
- JSON / XML 中的二进制字段:API 响应里嵌入二进制
性能注意
编码速度两者差不多,都不太可能成为瓶颈。但解码 Base64 时要注意填充处理,错误的填充会导致解码失败。Hex 的解码逻辑更简单,每两个字符直接映射一个字节。
# 命令行编码示例
echo -n "Hello" | xxd -p # hex: 48656c6c6f
echo -n "Hello" | base64 # base64: SGVsbG8=
Hex 输入清理(前缀与分隔符)
真实世界的 hex 很少是干净的偶数长度串:
| 形态 | 例子 | 清理不当的风险 |
|---|---|---|
0x 前缀 | 0x48656c6c6f | 把 0x 留给解码器 → 非 hex 报错 |
| 冒号 MAC | 01:23:45:67:89:ab | 把 : 当数据 |
| xxd / dump | 48 65 6c 6c 6f | 空格被计入字符 |
| 大写摘要 | 2CF24DBA… | 解码器大小写不敏感则无妨 |
把上述形式贴进 Base64 工具 的 Hex → Base64,对 Hello 应得到 SGVsbG8=,再确认往返一致。若处理的是整数(不是不透明字节串),用 进制转换器——它按「一个大整数」建模,不适合二进制 blob。
协议里两种编码混用时
TLS / 密码库常把密钥 存成 Base64 PEM,却把指纹 打印成 hex。JWT 段是 Base64URL;不少调试 UI 又把解码后的 header 字节显示成 hex。若不做「同一缓冲区两种视图」的核对,SGVsbG8= 和 48656c6c6f 会被当成两份不同的秘密。习惯:只编码一次,从同一字节显示两种视图(工具输出下的 Hex 对照行就是干这个的)。
指纹流程:用 SHA-256 哈希生成器 得到约定的 hex 摘要;仅当 API 字段要求时再 Base64——不要对 hex 文本再做一层 Base64。
在本地完成编码
无论你需要把 API 响应中的 Base64 字段解码、把图片转成 data URI,还是把数字在十六进制和十进制之间转换,都不应该把数据发到陌生服务器。
Base64 编解码工具、进制转换器 和 SHA-256 哈希生成器 都在浏览器本地完成所有处理。你的二进制数据、API 响应、配置文件都不会上传到任何服务器。这在处理包含密钥、用户数据或专有内容的数据时尤其重要。
排查注记
选型表把哈希摘要划给 hex 而不是更紧凑的 Base64(44 字符 vs 64 字符),理由明说是业界惯例和工具链都按 hex 设计——密度不是唯一标准。Hex 优势的第一条是可读性:每个字节单独可读、边界清晰,Base64 的 6 位分组会把字节边界打乱,调试二进制协议时这是关键差异。「协议里两种编码混用时」一节抓的是真实陷阱:TLS 把密钥存成 Base64 PEM、指纹却打印成 hex,不做「同一缓冲区两种视图」的核对,两串输出会被当成两份不同的秘密——工具输出下的 Hex 对照行正是为这个核验准备的。
总结:调试、短数据、哈希摘要选 hex;嵌入文本、大数据、URL 场景选 Base64。两者各有所长,理解它们的密度和可读性权衡就能做出合适选择。