RUNWEBTOOLS
繁體中文
資料格式與編碼

字元編碼:Unicode 與 UTF-8 詳解

更新 2026-07-06

你見過:本該讀作 José 的名字變成了 José,或者一個表情符號變成了一堆問號方框。這種亂碼有個名字 —— mojibake(文字化け) —— 而它幾乎總是字元編碼不匹配。本指南講清字元、Unicode 和 UTF-8 究竟是什麼,讓這類 bug 不再神秘。

電腦存的是數字,不是字母

在最底層,電腦只存數字(位元組)。要存文字,我們需要一張約定好的表,把每個字元映射到一個數字,再映射回來。這張表就是 字元編碼。如果一個程式用一張表寫文字,另一個程式用另一張表讀,數字就會被解讀成錯誤的字元 —— 你就得到亂碼。

ASCII:小小的起點

最早廣泛使用的編碼 ASCII 為 128 個字元定義了數字:英文字母、數字、標點和一些控制碼。這對英語夠用,但沒有位置留給 éüß😀,或世界各語言使用的成千上萬個字元。幾十年裡人人都發明了自己彼此不相容的擴充,這正是文字在系統之間穿行時會壞掉的原因。

Unicode:為每個字元分配一個數字

Unicode 是通用的解決方案:一個單一標準,為每種書寫系統裡的每個字元,外加符號和表情符號,分配一個唯一的數字 —— 稱為 碼點(code point)。碼點寫作 U+ 後跟一個十六進位數:

A   →  U+0041
é   →  U+00E9
你  →  U+4F60
😀  →  U+1F600

關鍵在於,Unicode 定義了 數字,但沒定義如何把它們存成位元組。那是一個單獨的決定 —— 而這正是 UTF-8 登場的地方。

UTF-8:Unicode 如何變成位元組

UTF-8 是把 Unicode 碼點編碼成位元組的一種方式,也是網路壓倒性使用的那種。它精巧的設計在於它是 變長的

  • 128 個 ASCII 字元各佔 1 位元組 —— 所以 UTF-8 與 ASCII 向後相容。
  • 大多數帶重音的拉丁字元以及希臘/西里爾字元佔 2 位元組
  • 包括中文、日文和韓文在內的大多數其他文字佔 3 位元組
  • 表情符號和更罕見的字元佔 4 位元組

這就是為什麼一個「100 字元」的字串並不總是 100 位元組:一個字元可能是好幾個位元組。它也解釋了那個經典的 José bug —— 那是 é 的 UTF-8 位元組,被當成較舊的西方編碼、一位元組一位元組地誤讀了。

字元、碼點和位元組

三個相關卻不同的概念不斷讓人栽跟頭:

  • 字元(Character) —— 人所看到的(字母 é)。
  • 碼點(Code point) —— 它的 Unicode 數字(U+00E9)。
  • 位元組(Byte) —— 它被儲存的方式(在 UTF-8 中,是兩個位元組 0xC3 0xA9)。

把碼點原樣寫出來看,往往是診斷文字問題最快的辦法 —— 例如,一個原來是不換行空格(U+00A0)的「空格」。我們的 Unicode 轉換器 會顯示任意文字背後的碼點,並在字元與跳脫序列之間轉換。

如何避免亂碼

  • 到處都用 UTF-8。 把檔案儲存為 UTF-8 並宣告它 —— 在網頁上用 <meta charset="utf-8">,在 HTTP 中用 Content-Type 的 charset,在資料庫中用 UTF-8 定序。
  • 從頭到尾保持一致。 大多數損壞發生在一方假設了不同編碼的邊界處。
  • 為正確的上下文跳脫。 要把特殊字元安全地放進 HTML,用 HTML 實體;要放進 URL,用 URL 編碼

簡短版:Unicode 給每個字元一個數字,UTF-8 把這些數字變成位元組,而如果人人都同意使用 UTF-8,文字就不再壞掉。

更多 資料格式與編碼

查看全部 資料格式與編碼 指南 →

本指南提到的工具