同一段二进制数据,用不同的 Base 编码写出来,长度可以差出一倍。选错编码有时只是多占点带宽,有时会让地址没法双击选中、验证码被用户看错,或者让 PDF 解析器直接报错。这里用同一段 15 字节的输入 Hello, Base64! 统一演示,把五种常见 Base 编码的输出摆在一起看。
一、同一件事的几种做法:把二进制变成可打印文本
Base 家族做的事只有一件:把不能直接放进文本通道的字节,映射成一组可打印字符。区别在于每组拿几个比特去换一个字符。Base16 每 4 比特换 1 个字符,Base32 每 5 比特换 1 个,Base64 每 6 比特换 1 个,Base85 把 4 字节(32 比特)整体换算成 5 个字符。每字符携带的比特越多,膨胀率越低,但字符集越大、实现越复杂、对通道的兼容要求也越高。
输入统一为 Hello, Base64!(15 字节),结果如下:
Base58 的精确输出取决于具体字母表(Bitcoin 版与 Flickr 版不同),它不是按位分组,而是按大整数除法运算,长度并不严格固定。Base85 的输出以 Python a85encode 为参考。
二、Base16(Hex):膨胀 100%,但调试最好读
Base16 就是十六进制。每个字节拆成两个 4-bit 半字节,分别映射到 0-9 和 A-F。15 字节的 Hello, Base64! 变成 30 个字符,长度翻倍。
它的膨胀率在家族里最高,换来的是零歧义:没有填充符,没有大小写变体带来的映射差异,任何文本编辑器、日志管道、人的眼睛都能直接读。哈希值展示、内存地址、颜色码、调试输出默认都用它,不是因为效率高,而是因为不需要额外解释。
在拿 Base64 结果做长度对比之前,可以先在 Base64 在线编码解码 里取一个基准值,再回到 Hex 看翻倍后的长度,直观感受可读性溢价有多大。反过来,把同一段 Hex 丢进 Hex 转 Base64,就能看到 30 个字符被压缩到 20 个的过程。
三、Base32:膨胀 60%,只在字符集受限时用
Base32 每 5 比特映射一个字符,字母表通常取 A-Z 加 2-7,刻意排除了 0/O 和 1/I/L 这类手写、口述时容易混淆的字符对。15 字节输入产出 24 个字符(含填充),膨胀 60%。
它比 Base64 长,之所以还要用,是因为通道限制比带宽更硬。TOTP 双因素验证码需要用户手动输入,字母表必须排除易混字符;DNS 子域名不区分大小写,Base32 天然无小写字母,不会因为大小写折叠导致解码歧义。Crockford Base32 进一步把字母表改为 0-9 加去除 I/L/O/U 的大写字母,专为人类转录设计。
Base32 为什么长:5 比特的映射粒度意味着每 5 个字节(40 比特)刚好编成 8 个字符,但输入不是 5 的倍数时就要补零加填充。相比 Base64 的 3 字节到 4 字符,Base32 的 5 字节到 8 字符在输入长度不规整时浪费更多。
四、Base58:Bitcoin 地址为什么去掉 0OIl/+
Base58 不是 2 的幂次编码。它直接拿掉 Base64 字母表里的 0(零)、O(大写 o)、I(大写 i)、l(小写 L),再去掉 + 和 /,剩下 58 个字符。
这六个字符被剔除的理由很具体:前四个在大多数字体下肉眼难辨,后两个会破坏双击选中整段字符串的体验(+ 和 / 在很多 UI 里不被视为单词字符)。Bitcoin 地址需要被用户从屏幕上抄写、从聊天记录里复制、在纸质钱包上印刷,字符歧义造成的资金损失不可接受。
代价是 Base58 的编解码走大整数除法,而不是 Base64 那种位移掩码,CPU 开销明显更高。它适合编码短而关键的标识符(地址、密钥指纹),不适合大批量二进制数据。
五、Base64:膨胀 33%,通用平衡点
Base64 每 3 字节(24 比特)切成 4 组 6 比特,映射到 A-Z、a-z、0-9、+、/。15 字节输入在补一个零字节后编成 20 个字符,膨胀 33%。
它是绝大多数场景的默认答案:MIME 邮件附件、Data URL 内嵌图片、JWT 的 payload 段、PEM 证书主体。原因不在效率最优(Base85 更优),而在生态覆盖最广:标准库到处都有,浏览器原生支持 btoa/atob,任何文本协议都认得它。
URL 场景下需要换用 Base64url 变体:+ 换成 -,/ 换成 _,填充 = 通常省略。这不是另一套编码,只是索引 62 和 63 换了个字符,避免在查询串和路径里被错误解析。
六、Base85 / Ascii85 / Z85:膨胀 25%,PDF 字体流与嵌入式设备为什么爱用
Base85 把 4 字节当作一个 32 位大整数,除以 85 取余,得到 5 个字符。膨胀率降到 25%,比 Base64 少浪费约 6 个百分点。
Ascii85 是 Adobe 为 PostScript 和 PDF 定义的变体,字母表取 ASCII 33 到 117(! 到 u),四个零字节可以缩写成单个 z,并用 <~ ~> 做帧定界。PDF 的字体流和嵌入图像用它,因为 PDF 解析器本来就按这个规则读。
Z85 是 ZeroMQ 的变体,字母表刻意排除了引号、反斜杠、逗号、分号等字符,使得编码结果可以直接粘进源代码字符串字面量里而不需要转义。代价是输入长度必须是 4 的倍数,且没有 z 零组缩写。
选 Base85 之前要先确认解码端认哪一套字母表。Ascii85、Z85、RFC 1924 的 Base85 三者输出互不兼容,用错变体解码会得到乱码或直接报错。同一份 JSON 配置,在 Base64 里是一个长串,在 Ascii85 里是另一个更短的串,换到 Z85 又变一次。用 JSON 转 Base64 可以拿来对照,但换到 Base85 时务必先对好变体名。
反过来核对时,Base64 转 Hex 能直接暴露两者在字节层面的等价性:Base64 和 Hex 不是竞争关系,只是同一堆字节的两种写法,互转是无损的。
七、一张选型表:字符集限制、膨胀率、可读性、是否 URL 安全
选型的第一原则不是哪个最短,而是传输通道允许什么字符。通道卡死的时候,膨胀率再好看也用不了。
按传输约束优先排序:通道只认十六进制,用 Base16;通道不区分大小写或需人工输入,用 Base32;通道是 URL 且需最短,用 Base64url;通道允许宽字符集且追求最小体积,用 Base85(先确认变体);地址类短标识需防抄错,用 Base58。
延伸阅读:Hex 与 Base64 互转拆解两种最常用写法之间的字节级对应关系;三种安全文本选型从攻击面角度比较 Base64、Base58、Base85 在令牌和标识符场景下的取舍。