前陣子幫同事處理文件出現亂碼的問題,因緣際會看到 Huli 大大寫的文章《為什麼打開檔案時會看到亂碼?跟著小明一起從傳紙條學習編碼》,對我這種技術麻瓜來說幫助很大,因此想結合查到的其他字元編碼相關資料,整理成文章。
先說結論:
亂碼就是在儲存跟顯示時使用了不同的編碼系統,可能導致的狀況,只要改用同一個編碼系統即可解決這個問題。
首先我們要知道電腦採取 二進位系統
來儲存資訊。也就是說所有資料都用一連串的 0 和 1 呈現。
二進位系統中最基本的單位是
位元 (bit)
,等於單一個 0 或 1下一級更大的單位是
位元組 (byte)
,等於 8 個位元,例如:01101011
以一篇文章來說,內容由非常多 字元
組成,而每個字元在電腦眼中都是一連串的位元,也就是一堆 0 和 1。
ASCII
ASCII
是美國於 1960 年代推出的標準編碼系統。
所謂編碼是指將人類文字轉換成電腦二進位的流程。
ASCII 支援以下符號:
大寫拉丁字母
小寫拉丁字母
阿拉伯數字 0 ~ 9
常用標點符號
ASCII 為每個符號指派一組獨一無二的 ASCII Code (三位數代碼組成),以及一個獨一無二的位元組。所以 ASCII 最多能儲存 2^8 = 256 個符號。
想想世界上那麼多語言使用不同的文字系統,加上 emoji 和各種顏文字,區區 256 個符號的扣打鐵定不夠,因此我們需要更先進、字元儲存量更大的編碼系統。
Unicode & UTF-8
Unicode
使用更複雜的機制,解決了 ASCII 空間不足的問題。每個符號還是會被分配到一組獨一無二的代碼,被稱為 code point
,以十六進位紀錄,大概長這樣:U+1F4A9
。
但 Unicode 本身不會將符號儲存為二進位。也就是電腦看不懂。
所以我們需要另一套編碼方法 UTF-8
將 Unicode 轉換為二進位。
UTF-8
會將 code point
轉換成 1 ~ 4 個位元組:
常見符號,例如 C,佔據 8 位元
罕見符號,例如 💕,佔據 32 位元
其他符號則占據 16 ~ 24 位元不等
這麼做的好處是能夠更彈性地節省空間。只需要一個位元組的符號,就讓它佔據一個位元組;需要三個位元組的符號,就佔據三個整。不多也不少,快樂沒煩惱。
題外話,由於 Golang 字串預設上用 UTF-8
編碼,所以我們可透過遞回去取得字串中每個字元的 code point
以及 byte index
。
|
|