每位軟體開發者都必須了解的 Unicode 與字元集基礎#
許多開發者對字元集、編碼與 Unicode 缺乏足夠的認識,導致程式中頻繁出現亂碼問題。這篇文章回溯字元編碼的歷史演進,釐清核心觀念。
ASCII 的起源與限制#
ASCII 使用 7 個 bit 來表示字元,涵蓋英文字母、數字與基本標點符號(0-127)。由於一個 byte 有 8 個 bit,剩餘的 128-255 範圍便成為各方爭搶的空間。
不同國家與廠商對 128-255 的定義各不相同,形成了所謂的 ANSI Code Page 系統。例如,在以色列使用的 Code Page 中,128-255 對應希伯來文字元,而在希臘的 Code Page 中則對應希臘字母。
同一個 byte 值在不同 Code Page 下代表完全不同的字元。這意味著一份文件若沒有標明使用的 Code Page,就無法被正確解讀。
亞洲語言的挑戰:DBCS#
對於中文、日文、韓文等擁有大量字元的亞洲語言,單一 byte 根本不夠用。DBCS(Double Byte Character Set,雙位元組字元集)應運而生——某些字元用 1 byte 表示,某些用 2 bytes,使得字串處理變得更加複雜。
Unicode 的誕生#
Unicode 的目標是為世界上所有書寫系統中的每個字元提供唯一的 Code Point。例如:
- U+0041 代表拉丁字母 ‘A’
- U+0639 代表阿拉伯字母 ‘Ain’
- U+4E2D 代表中文字「中」
常見迷思:「Unicode 就是 16-bit 編碼,最多 65,536 個字元」。這是過度簡化的誤解。Unicode 定義的是抽象的 Code Point,實際可容納的字元數遠超過 65,536。Code Point 本身只是一個概念性的數字,它如何在記憶體中儲存,取決於所選用的編碼方式。
編碼方式:從 Code Point 到 Binary#
Unicode Code Point 需要透過特定的編碼(Encoding)才能轉換為實際的 binary 資料。主要的編碼方式包括:
- UTF-8:與 ASCII 向下相容,英文字元仍用 1 byte,其他字元視需要使用 2-6 bytes。這是網路上最普及的編碼方式
- UCS-2 / UTF-16:以 2 bytes(或更多)為基本單位來表示字元。Windows 內部大量使用此編碼
- UTF-7:用於某些不支援 8-bit 的電子郵件系統
實務上的關鍵原則#
每一段字串都必須明確指定其編碼方式。沒有編碼資訊的字串是毫無意義的——你無法正確解讀它。
指定編碼的常見方式:
- HTTP Header:透過
Content-Type: text/html; charset=utf-8告知瀏覽器 - HTML Meta Tag:在 HTML 中使用
<meta charset="utf-8">宣告 - BOM(Byte Order Mark):在檔案開頭放置特殊的 byte 序列來標示編碼
為什麼瀏覽器會顯示亂碼?
當瀏覽器收到一段文字資料但不知道其編碼時,它只能猜測。猜錯的結果就是亂碼——原本正確的 byte 序列被用錯誤的 Code Page 或編碼方式來解讀,導致顯示為毫無意義的符號。
正確的做法是:在每個 HTTP 回應與 HTML 文件中明確宣告編碼方式,不要讓瀏覽器猜測。
身為開發者,最重要的一件事是:永遠不要假設字串的編碼。在儲存、傳輸或處理任何文字資料時,確保編碼資訊一併傳遞。若無特殊理由,優先選用 UTF-8。