AZ Tools
← 指南

数制与文本编码: 开发者速查表

数字和文本在计算机内部最终都成了同一种东西: 比特。但开发者不断在「对人友好」和「对机器友好」的表示之间切换 — 十六进制颜色码、Base64 令牌、经过 URL 转义的查询串。本指南是你每天会遇到的数制与编码的实用地图,以及它们各自到底是干什么的。

数制: 同一个值,不同的外衣

「数制(base)」不过是一个位置计数系统在进到下一位之前所用的不同数字的个数。十进制(基数 10)用 0–9; 二进制(基数 2)用 0 和 1; 八进制(基数 8)用 0–7; 十六进制(基数 16)用 0–9 再接 A–F。数本身在不同数制间并不改变 — 改变的只是写法。二进制的 11111111、八进制的 377、十进制的 255 和十六进制的 FF 都是完全相同的值。

十六进制受程序员青睐,是因为一位十六进制恰好对应四个比特(一个半字节),所以两位十六进制恰好是一个字节。这使十六进制成为紧凑且无损地阅读原始二进制的方式 — 这正是颜色(#FF8800)、内存地址和字节转储用它书写的原因。

在数制之间转换

这些转换纯粹是机械性的 — 正是工具应当替你完成的那类事 — 但了解运算的形状有助于你检验结果,并理解代码中 0x、0o、0b 前缀的含义。

  • 二进制 ↔ 十六进制: 从右起将比特每四个一组; 每组四位就是一位十六进制(1010 1100 = AC)。
  • 任意进制 → 十进制: 把每一位乘以它的位权(基数的位置次幂)再相加。
  • 十进制 → 任意进制: 反复除以基数; 把余数从最后到最先读出来,就是各位数字。

从字符到字节: UTF-8

文本在你编码之前并不是字节。字符集给每个字符分配一个编号(「码点」)— Unicode 就是那个通用标准 — 而编码决定这些编号如何变成字节。UTF-8 是网络上占主导的编码: ASCII 字符占一个字节,其他字符占两到四个字节,从而既让英文文本保持紧凑,又能表示一切文字系统和表情符号。

这就是为什么一个字符串以字符计的长度和以字节计的长度会不同: 'café' 是四个字符,但在 UTF-8 中是五个字节,因为 é 需要两个字节。哈希、大小限制和二进制格式都在意字节,所以这个区别在实践中很重要。

Base64: 作为安全文本的字节

Base64 做的是相反的工作: 它把任意字节变成由 64 个安全字符(A–Z、a–z、0–9,以及 + 和 /)组成的字符串。它之所以存在,是因为许多系统 — 电子邮件、JSON、URL、HTML 的 data: URI — 是为文本而建,可能破坏原始二进制。Base64 让你能通过纯文本通道完整地携带一张图片或一个密钥。

代价是体积: Base64 把每 3 个字节编码为 4 个字符,所以输出比输入大约大 33%。它是编码而非加密 — 任何人都能解码 — 因此它防的是传输中的损坏,绝不是窥探的目光。

URL 与百分号编码

URL 有自己的规则。在 URL 中具有特殊含义的字符(空格、&、?、#、/)必须以「百分号编码」表示,即一个 % 后跟其字节值的十六进制 — 空格变成 %20,和号变成 %26。这正是查询串能在不破坏地址的情况下携带任意文本的原因。

百分号编码作用于字符的 UTF-8 字节,这就把一切串联起来: 文本变成码点,码点变成 UTF-8 字节,字节变成 %XX 对。开发者遇到的大多数编码 bug,都来自把其中某一层与另一层混淆。

相关工具