
UTF-8 的誕生與原理:ASCII 相容、位元組數與 UTF-16 的差異
UTF-8 將 Unicode 字元編碼成位元組序列。它保留 ASCII 的位元組值,同時以 1~4 個位元組表示一個 Unicode 純量值。檔案大小、碼位數和畫面上的字元數,不能互相替代。
RFC 3629 記載,Ken Thompson 在 1992 年 9 月依照 Rob Pike 提出的設計條件構思這套編碼。以下從既有 Unix/Plan 9 程式的相容性需求,說明這些位元規則為何有用。
日文原文發布: 2026-05-02
從 ASCII 到 Unicode
ASCII 使用 7 位元,共有 128 個編碼位置,涵蓋英文字母、數字、基本符號與控制字元,但無法表達繁體中文或許多帶重音的字母。後來不同地區與系統採用 Big5、Shift_JIS、EUC-KR、ISO 8859 系列、Windows-1252 等編碼。
同一組位元組若用不同編碼解讀,可能得到完全不同的文字。Unicode 的構想是在共同的碼位空間中識別字元,減少各編碼系統彼此不相容的問題;碼位如何存成位元組,則由編碼形式決定。
1991 年的 Unicode 與早期 16 位元構想
Unicode Consortium 於 1991 年 1 月 3 日成立,同年 10 月出版 Unicode 1.0 第一卷。早期構想以 16 位元空間容納字元,不能與後來的可變長 UTF-16 混為一談。
將 ASCII 文字直接改存為 16 位元單位,會改變原本的位元組排列。例如 A 在 ASCII 是 0x41,以大端序的 16 位元形式則是 0x00 0x41。以 0x00 判斷字串結尾的 C 程式可能提早停止;還必須處理位元組順序,純 ASCII 文字所需空間也會增加。
1992 年的設計與標準化
RFC 3629 將設計歸於 Thompson,並說明 Pike 提供了設計條件。後續透過 X/Open 的國際化工作推進標準化,曾使用 FSS-UTF、UTF-2 與 UTF-8 等名稱。餐館軼事的細節不應取代可核對的標準化紀錄。
核心目標是保留 ASCII 的分隔符號與檔名處理方式,降低導入 Unicode 時必須改寫既有位元組處理程式的範圍。不過,能繼續處理位元組,不代表程式就會正確計算字元數。
UTF-8 的 1~4 位元組結構
表格若超出畫面寬度,可左右捲動。
| 碼位範圍 | 位元組數 | 位元模式 |
|---|---|---|
| U+0000–U+007F | 1 | 0xxxxxxx |
| U+0080–U+07FF | 2 | 110xxxxx 10xxxxxx |
| U+0800–U+FFFF,不含 U+D800–U+DFFF | 3 | 1110xxxx 10xxxxxx 10xxxxxx |
| U+10000–U+10FFFF | 4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
x 的位置承載碼位的位元。ASCII 保留原值,且 ASCII 位元組不會出現在多位元組序列內。接續位元組以 10 開頭;在合法序列中,最多往回找 3 個位元組即可找到起點。這是自我同步特性,不是修復損壞資料的保證。
U+D800–U+DFFF 保留給 UTF-16 代理碼,不能直接編成 UTF-8。C0 80 是過長編碼,ED A0 80 表示代理碼,F4 90 80 80 超過上限;這些序列及不完整的序列都不合法。只看開頭位元並不足以驗證。
UTF-8 沒有大端序或小端序之分。開頭的 EF BB BF 可作為 BOM 編碼標記,但不是位元組順序宣告。除了 U+0000,本來不會在字元編碼內出現 00;C 的 strlen() 仍計算位元組,strcmp() 也不會因此具備各語言的排序規則。
中文字一定占 3 個位元組嗎?
許多常用漢字、平假名與片假名在 UTF-8 中占 3 個位元組,但補充平面的漢字與部分表情符號需要 4 個。結合字元序列又可能包含多個碼位,因此不能把「一個看得見的字」固定算成 3 個位元組。
以日文資料為例,Shift_JIS/EUC-JP 中可用 2 個位元組表示的典型字元,在 UTF-8 中可能需要 3 個位元組。這種逐字比較不能直接當成整份網頁的增幅:HTML、CSS、JavaScript 也包含大量 ASCII,壓縮後大小還取決於內容與設定。
傳送端與接收端都使用 UTF-8,可減少編碼誤判;若把 UTF-8 位元組當成其他編碼,或將錯誤替代字元重新儲存,仍可能發生亂碼與資料遺失。
RFC 3629 將上限定為 4 個位元組
1998 年 1 月的 RFC 2279 曾允許最長 6 個位元組、到 U+7FFFFFFF 的序列。2003 年 11 月的 RFC 3629 取代它,將上限定為 U+10FFFF,最長 4 個位元組。兩份文件的作者皆為 François Yergeau。
此範圍與 Unicode、ISO 10646 及 UTF-16 的可表示範圍一致。合法的 Unicode 純量值序列能在 UTF-8、UTF-16、UTF-32 之間無損轉換;可表示範圍不等於已收錄字元數,因為仍有未指派碼位。
網頁宣告要與實際位元組一致
HTML 的字元編碼宣告、HTTP charset 與實際檔案內容應一致。只把宣告改成 UTF-8,不會轉換檔案。可用二進位編輯器檢查位元組,再確認接收端的解讀方式。
網站採用率與網路流量占比是不同指標。選擇編碼時應確認相容性、資料內容與交換流程,不能以測量對象不明的普及率代替實際驗證。
UTF-8、UTF-16 與 UTF-32 怎麼比較?
表格若超出畫面寬度,可左右捲動。
| 編碼 | 碼元寬度 | 每個純量值 | ASCII | U+3042 |
|---|---|---|---|---|
| UTF-8 | 8 位元 | 1~4 位元組 | 1 位元組 | 3 位元組 |
| UTF-16 | 16 位元 | 2 或 4 位元組 | 2 位元組 | 2 位元組 |
| UTF-32 | 32 位元 | 4 位元組 | 4 位元組 | 4 位元組 |
表中不含 BOM。Unicode 2.0(1996)引入代理碼與 UTF-16 的機制;補充字元首次加入則是 Unicode 3.1(2001)。UTF-16 以一個或兩個 16 位元碼元表示純量值,兩個碼元組成的代理對用於補充字元。
JavaScript 的 "😀".length === 2 計算 UTF-16 碼元。new TextEncoder().encode("😀").length === 4 才是 UTF-8 位元組數。結合字元可由多個碼位組成,因此 UTF-32 也不保證一個看得見的字只占 4 個位元組。
UTF-8 常用於網頁、檔案與 API;UTF-16 的碼元模型常見於 JavaScript、Java 與 Windows API;UTF-32 可用於需要逐碼位處理的內部表示。選擇時仍應區分儲存格式與程式語言的字串模型。
重點整理
- UTF-8 保留 ASCII,以 1~4 個位元組表示 Unicode 純量值。
- 1992 年的設計與 2003 年的範圍修訂是不同階段。
- 過長編碼、代理碼、超出上限與不完整序列都必須視為不合法。
- 位元組、碼元、碼位與畫面上的字元要分開計數。
- 確認 charset、BOM 與錯誤處理方式,並檢查轉換後的資料。
參考資料與來源
編輯說明
本文使用 AI 協助編輯,並於發布前由編輯確認。內容仍可能包含事實、解讀或時效上的錯誤;進行重要判斷前,請查閱所列的一手資料或官方文件。

