AlexSJC
AlexSJC
发布于 2026-11-08 / 2 阅读
0
0

Base 系列编码

Base 编码是一类把二进制数据映射为可打印字符的表示方法。常见的有 base16、base32、base36、base58、base62、base64、base85、base91、base92 等。它们共享同一套思路:按固定位数切分二进制流,再把每组数值映射到指定字符集;区别在于字符集大小、切分粒度和填充规则。

Base16

使用 16 个可打印字符(0–9 与 A–F)对字节数据编码。把输入按字节展开为二进制(不足 8 位高位补 0)后串联,再以 4 位为一组切分并转成十进制。

  • 编码后长度为原始数据的 2 倍:以 500 字节(4000 比特)的输入为例,编码后恰好是 1000 个字符。

  • 8 位恰好切成两组 4 位,因此 Base16 不需要填充符“=”。

  • 本质是一个标准十六进制字符串(是字符串而非数值),不含控制字符,也不含 Base64/Base32 里的“=”,人类与计算机都易读易处理。

Base32

使用 32 个可打印字符(A–Z 与 2–7)编码任意字节数据。编码结果不区分大小写,并排除了易混淆字符,便于人工识别与机器处理。

  • 主要用途是编码二进制数据,也能编码 ASCII 等二进制文本。

  • 将字节串的二进制值(不足 8 位高位补 0)串联后,以 5 位一组切分,每组转十进制再映射到 32 个字符之一。

  • 由于二进制传输以 8 位(1 字节)为单位,而 Base32 按 5 位切分,故切分后的数据长度必须是 40 比特的倍数(5 与 8 的最小公倍数)。

示例:输入单字节字符 &,其二进制为 100110,高位补 0 得 00100110。从左按 5 位切分00100 与 110;后组不足 5 位,末尾补 0 得 11000。两组分别转十进制后查表得到对应字符。此时仅用 10 比特,距 40 比特还差 30 比特(6 组),故末尾补 6 个“=”。

填充“=”主要用于满足部分程序的标准化处理,多数场景可省略;在 URL 中使用时必须去掉。

Base64

Base64 用 64 个可打印字符表示二进制数据。因 2⁶ = 64,每 6 比特为一个单元,对应一个可打印字符;3 字节(24 比特)对应 4 个 Base64 单元,即 3 字节由 4 个字符表示。

  • 字符集为 A–Z、a–z、0–9 共 62 个,另加两个可打印符号(不同系统可能不同)。

  • 常用作电子邮件的传输编码,也广泛用于在文本场景中表示、传输、存储二进制数据(如 MIME 邮件、XML 中的复杂数据)。

填充规则:若待编码字节数不能被 3 整除,末尾会多出 1 或 2 个字节,处理方式为——

  1. 用 0 字节在末尾补足至 3 的倍数,再进行 Base64 编码;

  2. 在编码结果后追加一个或两个“=”,表示补足的字节数。

具体地:剩余 2 个字节时,最后一个 6 位块有 4 位为 0,追加两个“=”;剩余 1 个字节时,最后一个 6 位块有 2 位为 0,追加一个“=”。

注:BinHex 使用不同的 64 字符集表示 6 位二进制数,但不称为 Base64。

Base85

Base85(又称 Ascii85)由 Paul E. Rutter 为 btoa 工具开发。它用 5 个 ASCII 字符表示 4 字节二进制数据,相比 Base64(4 字符表示 3 字节)效率更高:Base64 约增加 1/3 体积,Base85 约增加 1/4。

  • 应用场景:Adobe PostScript 与 PDF 文件格式,以及 Git 对二进制文件补丁的编码。

  • 与 Base64 一样面向可打印 ASCII 字符,但字符集更大,因此效率更高——用 5 个字符编码 4 字节(32 位)。

Base36

Base36 是把二进制数据表示为 36 进制字符串的编码方案。选用 36 是因为阿拉伯数字 0–9 与拉丁字母 A–Z 恰好构成 36 个字符,每个 base36 位所需信息少于 6 比特。

  • 有符号 32 位整数最多容纳 6 个 base36 位,64 位整数最多容纳 13 个。

  • 举例来说:一个有符号 32 位整数在 base36 下的表示不会超过 6 个字符,而 64 位整数不会超过 13 个字符。反过来说,用 base36 表示整数时,位数天然有上限,便于预估长度。

Base58

Base58 是 Bitcoin 中使用的编码方式,主要用于生成钱包地址。

相比 Base64,Base58 不使用数字 0、大写 O、大写 I、小写 l,也不使用 + 和 /。

设计动机:

  • 避免混淆:某些字体下 0 与 O、I 与 l 极为相似;

  • 避免非字母数字符号+/ 作为账号字符较难被接受;

  • 无标点:通常不会被从中间分行;

  • 便于选中:多数软件支持双击选中整个字符串。

Base91

basE91 用 91 个字符表示 ASCII 编码的二进制数据。它从 94 个可打印 ASCII 字符(0x21–0x7E)中省略三个字符来构建字母表:

  • -(破折号,0x2D)

  • \(反斜杠,0x5C)

  • '(撇号,0x27)

它是把二进制数据编码为 ASCII 的高级方法,类似 UUencode 或 Base64,但效率更高。开销取决于输入数据:最多约 23%(Base64 为 33%),最低可降到约 14%(常见于全 0 字节块)。因此 basE91 很适合通过二进制不安全的通道(如电子邮件、终端线路)传输较大文件。

Base92

Base92 相对小众,设计思路来自 thenoviceoof 的项目说明,要点如下:

  • 动机:Base64 有约 33% 的体积开销,Base85 约 20%,但可打印 ASCII 字符尚未被充分用尽,于是尝试进一步压缩开销。

  • 字符集:94 个可打印 ASCII 字符中,排除 ` 和 "(与普通引号 ' 过近),并把 ~ 用作特殊符号(空字符串),最终得到 92 个字符,故称 base92。

  • 每字符约 6.5 比特;一次取 13 位,用类似 Base85 的除法取模方案产出两个输出字符。相比 Base85,抗损坏性更好——一位错误只影响 2–3 个字节,而非 4 个字节。

  • 注意:某些需要特定输出的场景可能要求把 ~ 用作空字符串分隔符;但向解码器传入空字符串不会导致异常,因此不强制使用 ~。

  • 早期版本中,base92 输出长度与输入长度并非单调增长,现已修正。

  • 与 Base64、Base85 把较小字节整数干净映射到另一较小字节整数相比,base92 把 13 字节映射为 16 字符,体积上优于 Base85 的 4→5,但不甚优雅。

Base62

Base62 把数字转换为 ASCII 字符串(0–9、a–z、A–Z),反之亦然,通常得到较短的字符串。字符集为 26 个小写字母 + 26 个大写字母 + 10 个数字 = 62。

(1)62 进制与 10 进制互转

62 进制转 10 进制与 2 进制转 10 进制相似:从右往左,每个数乘以 62 的相应次方(次方从 0 开始),再求和。

10 进制转 62 进制则与 10 进制转 2 进制类似:不断除以 62 取余数,最后倒序排列。

(2)短 URL 转换

常见做法是维护一个全局自增 id:每来一个长 URL,就将其与一个自增 id 绑定,再用 Base62 把该 id 转成字符串,即完成短链转换。

结语

以上梳理了 Base 系列常见编码的基本原理与差异。核心无非三点:字符集大小、切分位数、填充规则。理解这三点,各类 Base 编码便不难区分与选用。

附录

组合

表示空间

a×2^n

a×10^n

4位 Base32

32⁴ = 1,048,576

1×2²⁰

1.05×10⁶

4位 Base36

36⁴ = 1,679,616

1.68×2²⁰

1.68×10⁶

4位 Base58

58⁴ = 11,316,496

1.13×2²³

1.13×10⁷

4位 Base62

62⁴ = 14,776,336

1.48×2²³

1.48×10⁷

6位 Base32

32⁶ = 1,073,741,824

1×2³⁰

1.07×10⁹

6位 Base36

36⁶ = 2,176,782,336

2.18×2³⁰

2.18×10⁹

6位 Base58

58⁶ = 38,068,692,544

3.81×2³³

3.81×10¹⁰

6位 Base62

62⁶ = 56,800,235,584

5.68×2³³

5.68×10¹⁰

8位 Base32

32⁸ = 1,099,511,627,776

1×2⁴⁰

1.10×10¹²

8位 Base36

36⁸ = 2,821,109,907,456

2.82×2⁴⁰

2.82×10¹²

8位 Base58

58⁸ = 128,063,081,718,016

1.28×2⁴⁷

1.28×10¹⁴

8位 Base62

62⁸ = 218,340,105,584,896

2.18×2⁴⁷

2.18×10¹⁴


评论