ASCII, Unicode, UTF-8? How do computers process text?

ASCII、Unicode、UTF-8、UTF-16?计算机是如何处理文本的?

前言

最近在 Go 处理字符串时发现对计算机处理文本的原理不是很透彻,因此翻阅更多教学文件了解计算机如何处理文本。

历史上计算机如何处理文本?

  1. 计算机存储与运算都是通过数字,而文本是由一系列数字进行编码
  2. 早期计算机厂商有各自的标准(EBCDIC🔗
  3. ASCII🔗(美国信息交换标准码)统一了英文常用的字符,采用 7 bit 来记录字符,并保留最高的 bit 用作奇偶校验位(parity bit),受限于当时传输错误率高且没有健全的协议处理
  4. 第 8 个 bit 之后也被不同标准扩充用于解释不同字符,但也带来标准混乱导致“乱码”的问题

更多字符扩充的需求

但像是汉字有上千上万个字符要如何应对呢?新标准:万国码 Unicode🔗,通过替世界上每个字符指派对应的码位 Codepoint🔗来解决。

UTF-8 vs UTF-16 vs UTF-32

前面提到的都是“某个数字对应某个字符”的标准,但具体来说文本应该如何被存储?Unicode Transformation Format 简称 UTF,其中数字代表存储的最小 bit 单位。

  1. 用过大的空间去存储字符是不经济的
  2. 新的存储格式标准要向后兼容 ASCII
  3. 已经有太多程序基于 8 bit 编码开发

基于以上考量,UTF-8 成为目前网络上最流行的编码格式。

UTF-32 的特点:

  • 每个字符都用 4 个 Byte 表示
  • 不兼容 ASCII
  • 处理简单,可以直接通过索引访问第 n 个字符
  • 浪费空间,很少被实际使用

UTF-16 的特点:

  • 每个字符都用 2 或 4 个 Byte 表示
  • 不兼容 ASCII
  • 大部分常用字符用 2 个 Byte 表示
  • JavaScript、Java 等语言内部采用此编码
const s = "😀"; // emoji 超出了 16 bit 范围
console.log(s.length); // 2 (不是 1!)

UTF-8 的特点:

  • 每个字符都用 1 ~ 4 个 Byte 表示
  • ASCII 兼容:对于 ASCII 字符只用 1 个 Byte,且编码完全相同
  • 自同步性(Self-synchronization):可以从任意位置开始解码,因为每个 Byte 的前几个 bit 会标示这是单独字符还是多 Byte 字符的一部分
我现在在字符的哪个位置
看到 0xxxxxxx → 「我在一个单字节字符」
看到 110xxxxx → 「我在一个双字节字符的开头」
看到 1110xxxx → 「我在一个三字节字符的开头」
看到 11110xxx → 「我在一个四字节字符的开头」
看到 10xxxxxx → 「我在多字节字符的中间某处」

延伸阅读