在編程和日常辦公中,你一定遇到過“亂碼”問題:明明寫的是“你好”,結(jié)果打開文件后卻成了 ??o?
。這個問題的根源,就在于字符編解碼, 本文將帶你從頭理清:
- Unicode 與 UTF-8 的關(guān)系
為什么需要編碼?
計算機只能存儲和處理 二進制數(shù)字,而人類使用的是文字,編解碼就是一座橋梁,把人類的文字和計算機的數(shù)字一一對應(yīng)起來:
例如:
- ASCII 里,字母
A
的編碼是十進制 65,16進制是0x41。 - GBK/UTF-8 中,“你”對應(yīng)的二進制就會不同。
編碼和解碼規(guī)則不統(tǒng)一就會出現(xiàn)“你寫的和我看到的不一樣”的情況(比如你用utf-8編碼來存儲一個文本,傳遞給我,我用GBK來解碼打開),也就是亂碼。
常見的編碼方式
- ASCII早期標(biāo)準(zhǔn),只包含英文+英文字符,1 個字節(jié)(0–127)。
- GBK/GB2312
- Unicode一個全球統(tǒng)一的字符集,給每個字符一個唯一編號,比如“你”是 U+4F60 。
- UTF-8Unicode 的一種實現(xiàn)方式,用可變長度字節(jié)表示字符,兼容 ASCII,節(jié)省存儲。
Unicode 與 UTF-8 的關(guān)系
很多人會把 Unicode 和 UTF-8 混淆,其實它們分屬不同層面:
- Unicode是字符集標(biāo)準(zhǔn),為全世界的每一個字符分配唯一編號(碼點)。
- “你” → U+4F60
其中:U+
:表示這是一個 Unicode 碼點(Unicode Code Point)。
4F60
:十六進制數(shù)字,表示這個字符的編號。
??????????換成十進制就是:4F60
?? = 20320??。
所以 U+4F60
就是 Unicode 給“你”這個漢字分配的唯一編號 20320
- UTF-8 / UTF-16 / UTF-32是編碼方式,用來把 Unicode 編號轉(zhuǎn)換為實際存儲的字節(jié)流。
舉例:“你”(U+4F60):
- UTF-8 →
E4 BD A0
(3 字節(jié)) - UTF-16 →
4F 60
(2 字節(jié),LE 序)
?? 可以這么理解:
- Unicode 是“全球字符身份證號”,解決“每個字符的唯一標(biāo)識是什么”的問題。
- UTF-8/16 是“存儲方案”,解決“怎么存起來這個唯一標(biāo)識”的問題。
為什么 UTF-8 最流行?
- 兼容性好UTF-8 對 ASCII 完全兼容,英文存儲不變。
- 通用性強支持所有語言,解決跨國開發(fā)、跨平臺協(xié)作問題。
- 互聯(lián)網(wǎng)普及HTML、JSON 等網(wǎng)絡(luò)協(xié)議幾乎都默認 UTF-8。
- 跨系統(tǒng)一致性Linux、Mac、現(xiàn)代 Windows 都推薦 UTF-8。
UTF-8 的基本原理
UTF-8 是 變長編碼:
例如:
A:41(1 個字節(jié))
你:E4 BD A0(3 個字節(jié))
這樣既保證了對英文文本的高效,又能覆蓋全世界的字符。
UTF-8具體規(guī)則大致是這樣的:
0xxxxxxx (1 字節(jié),ASCII)
110xxxxx 10xxxxxx (2 字節(jié))
1110xxxx 10xxxxxx 10xxxxxx (3 字節(jié))
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (4 字節(jié))
- 后續(xù)字節(jié)都以
10
開頭,避免和 ASCII 沖突。
舉個例子:
漢字 “你” → Unicode 碼點(唯一標(biāo)識)是 U+4F60
。
轉(zhuǎn)成 UTF-8 是三個字節(jié):11100100 10111101 10100000
編碼中的注意事項
1. 換行符差異
不同系統(tǒng)間交換文件時,如果工具沒處理好,就可能導(dǎo)致一行變多行,一般vscode等編輯器會提供選擇換行顯示的功能
2. BOM(Byte Order Mark)
BOM 是文件開頭的特殊字節(jié),用于標(biāo)識編碼(和字節(jié)序),方便程序正確解析文本。
- 有些 UTF-8 文件開頭會加 BOM (
EF BB BF
),表明自己是 UTF-8。 - 但很多工具(特別是 Linux 系統(tǒng)程序)會把 BOM 當(dāng)成內(nèi)容,從而出錯。
3. 混用風(fēng)險
- 用 GBK 保存的文件,如果用 UTF-8 打開,會顯示亂碼。
- UTF-8 文件如果硬套 GBK 打開,同樣會出現(xiàn)奇怪字符。
編輯器如何識別編碼?
很多人以為編輯器“自動識別”編碼格式的,其實背后有一套規(guī)則:
- BOM 標(biāo)記
- UTF-16 BE:
FE FF
有 BOM 時,編輯器幾乎能 100% 確定編碼。
- HTML:
<meta charset="UTF-8">
- Python:
# -*- coding: utf-8 -*-
編輯器會優(yōu)先參考這些。
- Windows 早期默認 GBK/Shift-JIS 等本地化編碼。
- 編輯器沒發(fā)現(xiàn) BOM 或聲明時,通常就按“系統(tǒng)/用戶配置”的默認來。
- 根據(jù)字節(jié)分布規(guī)律來推測。
- 但這種方式并不可靠,經(jīng)常出現(xiàn)誤判。
?? 所以:亂碼往往是“(在一臺設(shè)備)寫文件時用了一種編碼,(在另一臺設(shè)備不同的編輯器)讀文件時用另一種編碼”造成的。
編輯器與編碼操作:重新選擇編碼,究竟改了什么?
常見編輯器支持情況:
- VS Code底欄可切換“以某編碼重新打開”或“以某編碼保存”。
- Notepad菜單里直接切換 GBK、UTF-8(有/無 BOM)。
- JetBrains 系列
- Windows 記事本新版默認 UTF-8(帶 BOM),老版多為 ANSI。
關(guān)鍵區(qū)別:
- 重新以某編碼“打開”文件?? 相當(dāng)于換一副“眼鏡”看同樣的字節(jié)流,文件本身沒變。 以某編碼“保存”文件?? 真正把內(nèi)存里的字符重新編碼成新的字節(jié)流,從而改寫了文件。
一句話總結(jié):
- 打開時換更改編碼方式 = 不改文件,只改解碼方式。
未來的發(fā)展趨勢
- UTF-8 將成為事實標(biāo)準(zhǔn)
- 操作系統(tǒng)和編程語言也在統(tǒng)一過渡。
- 未來編輯器可能會結(jié)合 AI,幾乎零錯誤地推斷文件編碼。
- GBK、Shift-JIS 仍在少數(shù)存量項目中使用,但新系統(tǒng)和軟件基本都轉(zhuǎn)向 UTF-8。
總結(jié)
- 編碼是“人類文字 ?計算機中的數(shù)字”的橋梁。
- UTF-8 因兼容性和通用性成為最廣泛的標(biāo)準(zhǔn)。
- BOM、換行符、保存編碼方式等細節(jié)要格外注意。
- 編輯器識別編碼依賴 BOM、聲明、默認配置和啟發(fā)式猜測,并非全能。
- 重新選擇編碼方式保存文件,其實就是修改了文件內(nèi)容。
- 未來趨勢很明確:UTF-8 一統(tǒng)天下。
閱讀原文:原文鏈接
該文章在 2025/9/28 9:49:00 編輯過