Base94 是一种二进制转文本编码,使用所有 94 个可打印 ASCII 字符(不包括空格)。它比 Base64 实现更高的数据密度,当您需要尽可能紧凑地将二进制数据编码为可打印 ASCII 时非常有用。本文解释 Base94 的工作原理和使用场景。
什么是 Base94?
Base94 使用从 !(0x21)到 ~(0x7E)的 94 个可打印 ASCII 字符,不包括空格。这是可用的可打印、非空白 ASCII 字符的最大数量:
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
每个 Base94 字符表示大约 6.55 位数据(log₂(94) ≈ 6.55),而 Base64 是 6 位。这使 Base94 比 Base64 有大约 22% 更好的密度。
Base94 编码工作原理
Base94 将输入视为大整数并转换为 94 进制:
编码过程
- 将输入字节转换为大整数
- 重复除以 94,记录余数
- 将每个余数映射到 Base94 字符
- 余数(按相反顺序)组成编码字符串
输入字节: [0x48, 0x65, 0x6C] ("Hel")
作为整数: 4,610,412
4610412 ÷ 94 = 49047 余 14 → '6' (位置 14)
49047 ÷ 94 = 521 余 73 → 'o' (位置 73)
521 ÷ 94 = 5 余 51 → '7' (位置 51)
5 ÷ 94 = 0 余 5 → '%' (位置 5)
结果: "%7o6" (反转的余数)
注意:确切的字符映射因实现而异。上面的示例使用从 ! 开始的标准可打印 ASCII 范围。
Base94 vs Base64 vs 十六进制
| 编码 | 字符数 | 每字符位数 | 开销 | 使用场景 |
|---|---|---|---|---|
| 十六进制 | 16 | 4 | 100% | 密码学值、调试 |
| Base64 | 64 | 6 | 33% | 通用二进制转文本 |
| Base94 | 94 | ~6.55 | ~22% | 最大密度文本编码 |
密度比较
编码 32 字节(256 位)数据:
| 编码 | 输出长度 | 字符数 |
|---|---|---|
| 十六进制 | 64 | 64 |
| Base64 | 44(带填充) | 44 |
| Base94 | ~39 | ~39 |
与 Base64 相比,Base94 每 32 字节节省约 5 个字符。对于更大的数据,节省会累积。
字符集
Base94 使用可打印 ASCII 字符,但确切范围可能有所不同:
标准范围(0x21 - 0x7E)
- 字符:
!到~ - 不包括:空格(0x20)
- 最常见的实现
自定义范围
某些实现排除了在特定上下文中造成问题的字符:
- URL 不安全字符:
<、>、"、{、}、|、\、^、` - Shell 特殊字符:
$、`、\、"、' - 标记字符:
<、>、&
始终检查您的特定 Base94 实现使用哪个字符集。
与其他编码的比较
Base64
- 优点:标准化(RFC 4648),广泛支持,有 URL 安全变体
- 缺点:33% 开销
- 使用场景:兼容性重要,需要标准编码
Base94
- 优点:~22% 开销,最大密度
- 缺点:未标准化,实现较少,可能有字符集问题
- 使用场景:密度关键,受控环境
Base85(Ascii85)
- 优点:25% 开销,比 Base64 好
- 缺点:不同实现使用不同字符集(btoa、RFC 1924)
- 使用场景:需要比 Base64 更好的密度但标准 Base94 不可用
十六进制
- 优点:通用、简单、可调试
- 缺点:100% 开销
- 使用场景:密码学值、调试、人类可读性
实际应用场景
数据序列化
当为只接受可打印文本的系统序列化二进制数据时:
- 配置文件
- 数据库文本字段
- 日志条目
- 有大小限制的 API 响应
紧凑令牌
生成紧凑令牌用于:
- 会话标识符
- API 密钥
- 短 URL
- QR 码有效载荷
嵌入式系统
在内存受限的环境中,每个字节都很重要:
- 固件更新有效载荷
- 串行通信协议
- IoT 设备消息
密码学材料
更紧凑地编码密码学值:
- 配置文件中的密钥材料
- Nonce/IV 值
- 哈希摘要
实现注意事项
填充
与 Base64 不同,Base94 没有标准的填充机制。实现处理方式不同:
- 无填充:某些实现简单地省略填充
- 长度前缀:在输出中包含原始长度
- 终止符:使用特定字符标记结束
前导零
整数转换方法可能丢失前导零字节。常见解决方案:
- 在输出前加上前导零计数
- 在转换前给整数添加偏置
- 使用保留字节边界的不同算法
大整数算术
Base94 编码需要任意精度算术。大多数实现使用:
- 内置 BigInt 类型(JavaScript、Python、Java)
- 自定义大整数库
- 避免完整大整数表示的流式算法
字符映射
从值 0-93 到字符的映射可以是:
- 直接:值 + 0x21(从
!开始) - 查找表:特定需求的自定义映射
- 标准:特定发布的字符集
Base94 实践
JavaScript 示例
const CHARS = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; function base94Encode(buffer) { let num = BigInt('0x' + buffer.toString('hex')); if (num === 0n) return CHARS[0]; let result = ''; while (num > 0n) { result = CHARS[Number(num % 94n)] + result; num = num / 94n; } return result; }
Python 示例
CHARS = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~' def base94_encode(data): num = int.from_bytes(data, 'big') if num == 0: return CHARS[0] result = [] while num > 0: result.append(CHARS[num % 94]) num //= 94 return ''.join(reversed(result))
局限性
未标准化
Base94 没有像 Base64(RFC 4648)那样的官方 RFC。不同的实现可能:
- 使用不同的字符集
- 填充处理不同
- 字节边界处理不同
工具较少
与 Base64 相比,较少的库和工具支持 Base94:
- 没有内置浏览器/操作系统支持
- 较少的语言标准库
- 较少的社区文档
URL 安全性
标准 Base94 字符集包含 URL 不安全字符(<、>、" 等)。对于 URL 上下文:
- 改用 URL 安全的 Base64
- URL 编码 Base94 输出
- 使用排除 URL 不安全字符的自定义字符集
何时使用 Base94
使用 Base94 当:
- 最大密度至关重要
- 您控制编码和解码两端
- 传输支持所有可打印 ASCII 字符
- 您需要比 Base64 提供的更大密度
使用 Base64 当:
- 需要与现有系统兼容
- 标准工具很重要
- 需要 URL 安全编码
- 您正在与期望 Base64 的 API 交互
使用十六进制当:
- 调试密码学值
- 使用 HSM 工具
- 人类可读性重要
- 需要最大兼容性
在线工具
使用 Base94 编码器:
- 将二进制数据编码为 Base94 格式
- 将 Base94 解码回二进制
- 与 Base64 和十六进制的输出大小比较
- 使用不同输入数据进行测试
所有处理都在浏览器中进行——您的数据永远不会离开您的设备。