前言
近期在 Go 處理字串時發現對於電腦處理文字的原理不是很透徹,所以翻了更多教學文件了解電腦是如何處理文字的。
歷史上電腦如何處理文字?
- 電腦存儲與運算都是藉由數字,而文字是由一連串的數字來進行編碼
- 早期電腦廠商有各自的標準(EBCDIC)
- ASCII(美國訊息交換標準碼)統一了英文常用的字符,採用 7 bit 來紀錄字元,並保留最高的 bit 用作奇偶校驗位(parity bit),受限於當時傳輸錯誤率高且沒有健全的協議處理
- 第 8 個 bit 之後也被不同標準擴充用於解釋不同字符,但也帶來標準混亂導致「亂碼」的問題
更多字元擴充的需求
但像是漢字有上千上萬個字符要如何應對呢?新標準:萬國碼 Unicode,透過替世界上每個字符指派對應的碼位 Codepoint來解決。
UTF-8 vs UTF-16 vs UTF-32
前面提到的都是「某個數字對應某個字元」的標準,但具體來說文字應該如何被存儲?Unicode Transformation Format 簡稱 UTF,其中數字代表存儲的最小 bit 單位。
- 用過大的空間去存儲字元是不經濟的
- 新的存儲格式標準要向後兼容 ASCII
- 已經有太多程式基於 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 → 「我在多字節字符的中間某處」延伸閱讀
- UTF-8, Explained Simply - Nic Barker
- If You Can’t Explain UTF 8 vs Unicode, Watch This - LearnThatStack
- 一起成為新世紀文字藝術師:深入玩轉 Unicode 和 OpenType 系列 - chingru
- How Computers Store Text - ASCII, Unicode, UTF-8, UTF-16, and UTF-32 - NoBS Code