字符编码相关知识总结
1.?什么是字符
字符是書寫的最基本構建單元。字符可以表示字母、數字、標點、表意符號(比如漢字)、數學符號,或者其他的書寫基本單元。
不能把字符和字形相混淆。字符是唯一的,抽象的語言“原子”。字形是畫出每個符號時使用的特定方式。只有當用一種字形替代另一種字形,文本的意思發生了改變,才把這些字形看成是不同的字符。否則,這些字形就是同一個字符的不同風格的表示形式。
?
比如上圖中的九個字形,雖然形狀各異,但一看就知道是小寫字母a,所以這九個字形代表的是小寫字母a這同一個字符。
2.?編碼后的字符集(coded character set)
編碼后的字符集將整數映射到字符。編碼后的字符集經常用數組來實現,通過代碼數值來進行索引。數組的元素就是字符。下面舉例說明一些常見的編碼后字符集。
1)?US-ASCII
ASCII表示“美國標準信息交換代碼”(American Standard Code for Information Interchange)。ASCII是最著名的編碼后字符集,早在1968年就由ANSI進行了標準化。ASCII的代碼值范圍是0到127(用十六進制表示是0x00到0x7F),因此只需7個二進制碼就可以覆蓋整個代碼空間。ASCII的推薦名稱是US-ASCII,這樣可以和那些7位字符集的一些國際化變體進行區分。HTTP報文(首部、URI等)使用的字符集是US-ASCII。
?
2)?iso-8859
iso-8859字符集標準是US-ASCII的8位超集,使用二進制碼的高位增加了一些國際化書面字符。有額外的二進制碼增加的空間(多了128個代碼,從0x80到0xFF)還不夠大,甚至還不夠所有的歐洲字符使用,更不用說亞洲字符了。因此iso-8859為不同地區定制了不同的字符集。其中最著名的就是iso-8859-1,用于表示西歐語言(英語、法語等)。iso-8859-1的別名是Latin1,是HTML的默認字符集。
3)?UCS
UCS(Universal Character Set)把全世界的所有字符都整合到了單一的編碼后字符集中。UCS由ISO 10646定義。Unicode是遵循UCS標準的商業化聯合組織。
在UCS標準中,代碼空間被分成了17個平面(planes),每個平面有65536(2的16次方)個代碼點(code points),所以總共有1,114,112個代碼點。這個數字很奇怪,因為它不是2的冪。這其實是UTF-16編碼方案的設計所造成的結果。
在UTF-16中,用兩個代碼單元(共四個字節)組成的“代理對”(surrogate pair)來編碼1到16平面中的2^20個代碼點(2^4個平面乘以每個平面2^16個代碼點),而對0平面進行編碼只需要一個代碼單元(兩個字節)。2^20 + 2^16 = 1024^2 + 65536 = 1114112。
?
UCS中的第一個平面,0平面,也叫“基本多語種平面”(Basic Multilingual Plane,BMP)。這個平面是到目前為止大部分字符所在的地方。而BMP中的大部分代碼點都被用于對中日韓的字符進行編碼。上圖中淺灰色區域中,0xD800到0xDFFF(8 * 2^8 = 2^11 = 2048)這個區域(倒數第三行后半部分)不對應任何字符,而是被保留用于在UTF-16編碼方案中對代理對進行編碼。
3.?字符編碼方案(character encoding scheme)
字符編碼方案(character encoding scheme)和編碼后的字符集(coded character set)不是一個概念。字符集給所包含的每個字符分配一個整數編號,而編碼方案規定如何把字符的代碼數字打包裝入二進制的比特數據中,以及如何在另一端將其解包回字符代碼。
?
字符編碼方案主要有以下3種類型。
固定寬度
固定寬度方式的編碼用固定數量的比特表示每個編碼后的字符。它們能被快速處理,但可能會浪費空間。
可變寬度
可變寬度方式的編碼對不同的字符代碼數字采用不同數量的比特。對于常用字符,這樣可以減少所需的位數,而且還能在允許使用多字節來表示國際性字符的同時,保持對傳統8位字符集的兼容性。
可變寬度(有模態)
有模態的編碼使用特殊的“轉義”模式在不同的模態之間進行切換。例如,可以用有模態的編碼在文本中使用多個互相重疊的字符集。有模態的編碼處理起來比較復雜,但可以有效地支持復雜的書寫系統。
1)?8位編碼
iso-8859字符集家族系列使用的是8位的恒等編碼。這種編碼把每個字符代碼直接編碼為相應的8位二進制數值。這種編碼方式只支持代碼范圍包含256個字符的字符集。
2)?UTF-8
UTF-8是一種流行的為UCS設計的字符編碼方案,UTF表示UCS變換格式(UCS Transformation Format)。UTF-8為字符代碼值使用的是無模態的變寬編碼。第一個字節的高位表示編碼后字符所用的字節數,后續每個字節都固定包含6位的代碼值。
?
如果編碼后的第一個字節的最高位是0,則編碼長度就是一個字節,剩余的7位就包含字符的代碼。這樣一來就美妙地達到了與ASCII的兼容(但和iso-8856系列不兼容)。
例如字符代碼90(ASCII的“Z”)在0到127的范圍內,故只需一個字節進行編碼(90 = 64 + 16 + 8 + 2 = 2^6 + 2^4 + 2^3 + 2,編碼為0,101,1010)。而代碼5073需要13位二進制數(1,001111,010001),會被編碼為3個字節(見上圖第三行):
11100001? 10001111? 1001001
注意UTF-8的最大編碼值是31位,能編碼2^31個代碼值,這遠遠大于UCS的代碼范圍(相當于2^15,即32768個平面)。
3)?UTF-16
UTF-16編碼方案能夠對UCS中的1,112,064個代碼點進行編碼(1,114,112減去從U+D800到U+DFFF這2048個用于代理對的代碼點)。UTF-16編碼長度要么是兩個字節(對于從U+0000到U+D7FF,以及從U+E000到U+FFFF的基本平面代碼點),要么是4個字節(對于從U+1,0000到U+10,FFFF的16個輔助平面中的代碼點)。
輔助平面中的代碼點長度超過兩個字節,用兩個16位的代碼單元(稱為一個代理對)來進行編碼,具體編碼方式如下:
- 將代碼點的值減去0x1,0000,得到一個20比特的范圍在0到0xFFFFF之間的數。(輔助平面本身有16 * 2^16 = 2^20個代碼點。)
- 20個比特中的頭10個比特(0到0x3FF之間的數)與0xD800相加,得到第一個代碼單元或者叫高位代理(lead surrogate),該值在0xD800到0xDBFF之間。
- 低位的10個比特(值同樣在0到0x3FF之間)與0xDC00相加,得到第二個代碼單元,或者叫低位代理(trail surrogate),取值范圍是0xDC00到0xDFFF。
從這里就能看出為什么要保留0xD800到0xDFFF這個范圍了,因為0xDFFF – 0xD800 + 1等于0x800,等于2 * 2^10,即切成兩半,每一半可以代理表示2^10個數,組合起來正好可以代理表示2^20個輔助平面中的代碼點(2^10 * 2^10 = 2^20)。
思考一下為什么要用代理對來進行編碼,而不是用4個字節直接表示輔助平面中代碼點的值?
轉載于:https://www.cnblogs.com/lihaiyang/archive/2013/03/16/2963631.html
總結
以上是生活随笔為你收集整理的字符编码相关知识总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 反射中 BindingFlags标识
- 下一篇: 首记,一种新的企业信息化平台开发方案——