一文帶你搞懂字符集編碼
軟件開發人員經常遇到 “中文亂碼”、“軟件不能顯示日文” 等類似問題。真相只有一個——對字符集編碼沒有一個系統的認知。
常見字符集編碼有 GB2312、GBK、BIG5、UTF-8、UTF-16,甚至有些從事 MFC 開發的人可能還會說字符集有 ANSI 和 UNICODE。真的是這樣嗎?直接上乾貨。
字符集分類
1. ANSI
American National Standards Institute 美國國家標準學會,由這個標準學會制訂的一種編碼規則。
-
採用多字節系統 (MBCS) 的變長編碼,每個字符可以是單個字節、雙字節,也可以是多字節的;
-
兼容單字節字符集 (SBCS) 和雙字節字符集 (DBCS);
-
兼容 EUC/EUC-CN 雙字節編碼。由於兼容了這個編碼,那麼 ANSI 的雙字節編碼也是大端存儲 (Big Endian) 的了;
-
不同的國家和地區可以使用不同的編碼規則,這些編碼對應到這些國家和地區的代碼頁 (Code Page) 上。
1.1. ASCII 編碼
ASCII 編碼即美國信息交換標準代碼(American Standard Code for Information Interchange)是一套共有 128 個字符的編碼,它基於阿拉丁字母,主要作用是用來表示英語和西歐語言字符。ASCII 規範編碼第一次公佈於 1967 年,ascii 碼在 1986 年完成最後一次更新。ASCII 碼對照表等同於國際標準 ISO/IEC 646,ASCII 碼對照表是世界最通用的信息交換標準。
ASCII 編碼
1.2. GB2312 編碼
GB2312 簡體中文編碼,一個漢字佔用 2 個字節,在大陸是主要的編碼方式,兼容 ASCII 編碼。
爲了支持繁體字,於是推出了 GBK 編碼,GBK 是國標擴展(Guo Biao Kuozhan)編碼的縮寫,兼容 GB2312。
爲了支持少數名民族的文字,於是推出了 GB1803,解決了中文、日文、朝鮮語等的編碼,兼容 GBK。
中文編碼
2. UNICODE 編碼
Unicode 又稱爲統一碼、萬國碼、單一碼,是國際組織制定的旨在容納全球所有字符的編碼方案,包括字符集、編碼方案等,它爲每種語言中的每個字符設定了統一且唯一的二進制編碼,以滿足跨語言、跨平臺的要求。
Unicode 字符集被劃分爲 17 個平面 (即,17 個區,編號爲 0-16),且具有以下特點:
-
每個平面有 216 = 65536 個代碼點,因此,整個 Unicode 字符集共有 17 × 65536 = 111 4112 個碼點。
-
整個 Unicode 字符集的碼點空間爲 U+000000 ~ U+10FFFF
-
每個平面的碼點範圍可表示爲 U+xx0000 ~ U+xxFFFF,其中 xx 表示 16 進制的 0x00 到 0x10,比如,平面 0 的碼點範圍爲 U+000000 ~ U+00FFFF,平面 2 的碼點範圍爲 U+020000 ~ U+02FFFF,平面 15 的碼點範圍爲 U+0F0000 ~ U+0FFFFF
-
再次注意:並不是每個碼點就一定對應有一個字符,因爲,目前 Unicode 字符集中有很多碼點都還未被使用。
Unicode 17 層平面
2.1. UTF-16 編碼
UTF-16 編碼源於 UCS-2,是 Unicode 最早的編碼方式。
-
UCS-2 編碼僅覆蓋了基本平面 (即 BMP,第 0 平面) 中的碼點,使用固定的兩字節將字符編號 (類似於 Unicode 中的碼點值) 直接映射爲字符編碼,中間未經過任何的編碼算法轉換。
-
很明顯,16 位的二進制位 (範圍爲 0x0000 ~ 0xFFFF) 無法表示 Unicdoe 引入的增補平面中的碼點 (平面 1 ~ 16,碼點範圍爲 0x10000~0x10FFFF),爲此,Unicode 在 UTF-16 編碼中使用“代理(代替) 機制”來解決這個問題,代理機制使用 4 個字節來表示增補平面中的碼點,從而使 UTF-16 成爲一種變長編碼方式。
因此,若軟件僅支持 UCS-2 編碼,則意味着僅支持 UCS 字符集或 Unicode 字符集基本平面中的字符,而不支持增補平面中的字符。
UTF-16 編碼後的碼元序列在映射爲物理意義上的字節序列時,又分爲 UTF-16BE (大端序),UTF-16LE (小端序)兩種情況,大端序和小端序又分爲帶有字節序標記 (with BOM) 和不帶字節序標記 (without BOM) 兩種情形。比如,“ABC”這三個字符的 UTF-16 編碼 (碼元序列) 爲:00 41 00 42 00 43;其對應的各種字節序列如下表所示:
”abc” 的各種 UTF-16 編碼
2.2. UTF-32 編碼
UTF-32 是一種將 Unicode 字符編碼的協定,對每一個 Unicode 碼位使用恰好 32 位元。其它的 Unicode transformation formats 則使用不定長度編碼。因爲 UTF-32 對每個字符都使用 4 字節,就空間而言,是非常沒有效率的。特別地,非基本多文種平面的字符在大部分文件中通常很罕見,以致於它們通常被認爲不存在佔用空間大小的討論,使得 UTF-32 通常會是其它編碼的二到四倍。雖然每一個碼位使用固定長定的字節看似方便,它並不如其它 Unicode 編碼使用得廣泛。
與 UTF-16 一樣,也存在大端和小端存儲。
2.3. UTF-8 編碼
UTF-8 編碼是 Unicode 編碼的一種編碼形式。由 1-6 個字節表示一個字符,兼容 ASCII 編碼。
UTF-8 編碼
3. MFC 中的字符集
MFC 字符集選擇多字節編碼時,對應的編碼是 GBK 編碼
MFC 字符集選擇 Unicode 編碼時,對應的編碼是 UTF-16 編碼。
4. QT 中的字符集
QString 是按 UTF-16 存儲的。
1、當選擇 UTF-8 編碼時,QString 構造函數的參數對應 UTF-8 編碼(默認設置)。
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec);
QString str = “右邊是UFT-8編碼的字符串”;
2、當選擇 GBK 編碼時,QString 構造函數的參數對應 GBK 編碼。
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec);
QString str = “右邊是GBK編碼的字符串”;
3、QString 也可以指定編碼賦值。
QString str1 = QString::fromLocal8Bit(“GBK編碼字符串”);
QString str2 = QString::fromUtf8(“UTF-8編碼字符串”);
作者: 你的程序猿大叔
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/OWk0HsRKb3LrfZo_De7OjA