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 → 「我在多字節字符的中間某處」

延伸閱讀