字符集相關的概念
字符集&編碼
- charset 是 character set 的簡寫,即字符集。
- encoding 是 charset encoding 的簡寫,即字符集編碼,簡稱編碼。
編號 編碼
- 字符 <–> 編號 <–> 編碼
- 編號不涉及具體使用多少字節來表示、是用定長仍是變長方案等細節問題。編號僅僅是一個抽象的概念,將具體字符映射到一個惟一的code上,是把字符數字化的一個過程。
- 字符集是一組映射關係[字符 - 編號] ,即對字符的數字化抽象,但不體現具體的編碼轉換格式。如Unicode就是一個字符集。
- 編碼是編號的具體存儲方式,將抽象的編號轉化成具體的編碼 - 編碼對應[存儲字節數、是否變長...]
下面具體以將Unicode展開講解正則表達式
Unicode字符集
- Unicode 是 Unicode Standard(Unicode標準)的簡寫,因此 Unicode 便是指 Unicode 標準。
- 它脫離具體平臺、語言,給每個字符 一個惟一的數字 -- 碼點(code point)
-
碼點的格式 U+[XX]XXXX X:表明一個十六制數字
能夠有 4-6 位,不足 4 位前補 0 補足 4 位,超過則按是幾位就是幾位。具體示例:編碼
- U+0048(不足 4 位前補 0 )
- U+4F60
- U+1D11E(超過4位則按實際位數)
-
範圍[U+0000,U+10FFFF] 理論大小爲 10FFFF+1=110000(16進制) 是一個百萬級別的數。設計
10FFFF + 1 = 110000(16) = (16 + 1) * FFFF = 17 * 16^4 = 17 * 65536(10)
能夠拆分出 17 個 範圍爲FFFF的平面
-
平面[Plane]爲了更好分類管理如此龐大的碼點數,把每 65536 個碼點做爲一個平面,總共 17 個平面。代理
- 第一個平面稱爲 BMP(Basic Multilingual Plane 基本多語言平面),也叫 Plane 0,它的碼點範圍是 U+0000 ~ U+FFFF
- 後續的 16 個平面稱爲 SP(Supplementary Planes)。範圍超過了 U+FFFF 即超過了 2個byte = 16 bit (2^16)個的理論上限
-
CJK 統一漢字(CJK:Chinese, Japanese, and Korean,中日韓)在first plane 中間很大一片區域code
流傳配置漢字的正則表達式 [\u4E00-\u9FA5] 就是plane 0 中這個範圍的 Unicode值,嚴格來講是不許確的。
-
代理區 BMP中還有一片空白,這段空白從 D8~DF。其中前面 D800–DBFF 屬於高代理區(High Surrogate Area),後面的 DC00–DFFF 屬於低代理區(Low Surrogate Area),各自的大小均爲 4×256 (2^8) = 1024
這兩個區組成一個二維的表格,共有1024×1024=210×210=24×216=16×65536,因此它剛好能夠表示增補的 16 個平面中的全部字符。orm
高代理稱爲Lead,低代理位Trail,一高一低便是一個代理對
映射關係,有圖表示
例如:
(D8 00 DC 00)—>U+10000,左上角,第一個增補字符
(DB FF DF FF)—>U+10FFFF,右下角,最後一個增補字符
Unicode的具體編碼格式
三種編碼方案的定變長與字節數總結:it
- UTF-8 :變長,1-4 字節;
- UTF-16:變長,2 或 4 字節;
- UTF-32:定長,4 字節。
定長與變長
- 在容量 和 效率之間全行,出現了變長的編碼方案。
- 變長的設計核心在於區分不一樣的變長字節:利用高位區分,利用代理區區分
- 默認標示位(高位來區分)的變長方案,損失了不少有效碼位
- 代理區作區分的方案(保留一部分code【70-80】排列組合,映射出70*80 100個code)
具體編碼實現
UTF 便是 Unicode 轉換格式(Unicode (or UCS) Transformation Format)io
-
UTF-32form
- 碼點最大的 10FFFF 佔 21 位,UTF-32 採用的定長4 byte 則是 32 位。高位補 0 的形式補夠 32 位便可,缺點佔用空間太大。
- 4字節 XXXX XXXX , XXXX XXXX , XXXX XXXX , XXXX XXXX
-
UTF-8效率
- 變長的編碼方案:1,2,3,4 四種 byte 組合
-
採用高位保留方式 來區別不一樣變長
- 1字節 0XXX XXXX (7)
- 2字節 110X XXXX 10XX XXXX ) (11)
- 3字節 1110 XXXX 10XX XXXX 10XX XXXX (16)
- 4字節 1111 0XXX 10XX XXXX 10XX XXXX 10XX XXXX (21)
-
碼點對應字節
- 編碼轉二進制數,去掉高位0 判斷採用幾字節
- 一字節 有效位7位(2^7 = 128)兼容ASCII,[碼點] U+0000 ~ U+007F (0~127)
-
二字節 11位有效,2^11 = 2048 個編碼空間 碼點 U+0080 ~ U+07FF (128~2047)
- 由於去掉了一字節的碼點,二直接碼點從 128~2047,因此不會佔滿 2048 個編碼空間,是有冗餘的,下面一樣如此
-
三字節 16位有效,65536 個編碼空間 碼點U+0800~U+FFFF (2048~65535)
- 一樣三字節碼點範圍 U+0800~U+FFFF(2048~65535)
- 存着絕大部分漢字(經常使用字),還有不少偏門漢字保存在增補平面中
- 四字節剩餘 21位有效位數,最大的Unicode碼點 10FFFF(1 + 4 * 5) 也是 21 位,恰好囊括。U+FFFF 以上的增補平面的字符都在這裏表示
- 按照 UTF-8 的模式,它還能夠擴展到 5 字節,乃至 6 字節變長,但 Unicode 說了碼點就到 10FFFF,不擴充了,因此 UTF-8 最多到四字節就足夠了
-
碼點轉換爲UTF-8編碼
- 將碼點轉換成 2進制
- 將二進制數 按照UTF-8 固定位分組
- 選中幾字節模式後,高位不足 補0
-
從新將 2進制數 轉換成16進制數
漢字「你」 (U+ 4F60)
轉2進制 :U+ 4F60 -> 0100 1111 0110 0000 (16位 按照3字節轉換)
分組 :0100 1111 0110 0000 -> 0100 1111,01 10,0000 (3字節 4+6+6)
替換有效位:1110 0100 1011 1101 1010 0000
按字節轉16進制:E4 BD A0
- UTF-8 三字節模式固定了 1110 的開頭模式,因此多數漢字老是以 1110 開頭,換成 16 進制形式,1110 就是字母 E。
若是看到一串的 16 進制有以下的形式:EX XX XX EX XX XX…
每三個三個字節前面都是 E 打頭,那麼它極可能就是一串漢字的 UTF-8 編碼了
-
UTF-16
- BMP中的碼點,直接對應無需轉換 (plane 0 範圍2byte = 16bit,16位恰好對應)
-
變長的 2 或 4 字節編碼模式
- BMP內的字符使用 2 字節編碼
- 其它的則使用 4 字節組成所謂的代理對來編碼
-
代理區
- 鳥瞰圖中,一片空白的區域,就是代理區(Surrogate Area),
- 爲了編碼增補平面中的字符而保留的,總共有 2048 個位置,均分爲高代理區(D800–DBFF)和低代理區(DC00–DFFF)兩部分,各1024,這兩個區組成一個 二維的表格,共有:
1024 × 1024 = 2^10×2^10 = 2^4×2^16 = 16×65536
- 它剛好能夠表示增補的 16 個平面中的全部字符
-
碼點轉換
- BMP 中直接對應,無須作任何轉換
-
增補平面 SP 中:
- 減去10000(16進制)[第一個平面中的全部碼點]
- 除以代理區的行寬[ 1024(10進制) ] 商:第幾個高代理區 餘數:第幾個低代理區
- Lead = (碼點 – 10000(16)) ÷ 40016 + D800
Trail = (碼點 – 10000(16) % 40016 + DC00
- 實際轉換用API, 經過位移運算更高效