ASCII碼:
???? C語(yǔ)言中,一個(gè)字節(jié)對(duì)應(yīng)八位二進(jìn)制數(shù),每一位二進(jìn)制數(shù)就有0窥妇、1兩種狀態(tài),所以一個(gè)字節(jié)有2^8=256種不同的狀態(tài)娩践,美國(guó)人最早用一字節(jié)的數(shù)據(jù)表示256個(gè)字符活翩,稱為ASCII碼。ASCII定義了128個(gè)字符翻伺,也就是只使用了8位二進(jìn)制數(shù)的后七位材泄,最前面的一位統(tǒng)一規(guī)定為0
Unicode:
問(wèn)題:
?128個(gè)字符來(lái)編碼英文是完全足夠的,但是用來(lái)表示其他語(yǔ)言吨岭,128個(gè)字符是遠(yuǎn)遠(yuǎn)不夠的拉宗,即便用上閑置的最高位,不同國(guó)家的編碼會(huì)不一樣辣辫。最終旦事,美國(guó)人意識(shí)到提出一種標(biāo)準(zhǔn)方案來(lái)展示世界上所有語(yǔ)言中的所有字符, unicode由此誕生了络它。
???? Eg:
“漢”字在unicode碼點(diǎn)是0x6c49需要兩個(gè)字節(jié)來(lái)表示族檬,轉(zhuǎn)化為二進(jìn)制數(shù)110110001001001就是他的編碼,但是問(wèn)題又來(lái)了化戳,當(dāng)你譯碼時(shí)单料,比如看到的兩個(gè)字節(jié),那它到底表示的是一個(gè)兩字節(jié)字符還是兩個(gè)一字節(jié)字符点楼。
為了解決這個(gè)編碼問(wèn)題扫尖,編碼采用定長(zhǎng)編碼,選字節(jié)的編碼方式掠廓,即4字節(jié)編碼换怖。
?
UTF-8:
這種情況下,編碼譯碼都能實(shí)現(xiàn)一對(duì)一蟀瞧,但是又出現(xiàn)了一點(diǎn)小bug:空間的浪費(fèi)(字符不足四字節(jié)時(shí)沉颂,高位全部補(bǔ)零),所以我們能不能想一種辦法既能解決unicode的譯碼譯碼問(wèn)題又不會(huì)浪費(fèi)空間呢悦污?UTF-8解決了這個(gè)問(wèn)題铸屉。(既然譯碼時(shí)識(shí)別不出一個(gè)字節(jié)和多個(gè)字節(jié)的字符,那就在多字節(jié)字符上面做一些標(biāo)志位)
UTF-8可以根據(jù)字符的不能變換長(zhǎng)度切端,使用1-4個(gè)字節(jié)表示一個(gè)字符彻坛。編碼規(guī)則如下:
[if !supportLists]1)? [endif]單個(gè)字節(jié)的字符,同unicode(向后兼容)
[if !supportLists]2)? [endif]對(duì)于需要N個(gè)字節(jié)來(lái)表示的字符(N > 1),第一個(gè)字節(jié)的前N位都設(shè)為1昌屉,第N + 1位設(shè)為0钙蒙,剩余的N – 1個(gè)字節(jié)的前兩位都設(shè)為10,剩下的二進(jìn)制位使用這個(gè)字符的unicode碼點(diǎn)來(lái)補(bǔ)充间驮。如下:
Unicode 十六進(jìn)制碼點(diǎn)??????????? ??UTF-8二進(jìn)制
00000 0000 – 0000 007F? 2^4 + 2^3???0xxxxxxx????????????????????????? 2^7
00000 0080 – 0000 07FF? 2^7 + 2^4???110xxxxx 10xxxxxx?????????????????2^11
00000 0800 – 0000 FFFF? 2^11 + 2^5??1110xxxx 10xxxxxx 10xxxxxx??????????2^16
00001 0000 – 0010 FFFF? 2^16 + 2^5??11110xxx10xxxxxx 10xxxxxx 10xxxxxx?? 2^21
Eg:
“漢”字unicode的碼點(diǎn)0x6c49(2^4+2^4+2^4+2^3)躬厌,原本只需要兩字節(jié)表示,高位補(bǔ)零即可竞帽。但是這里添加了標(biāo)志位烤咧,對(duì)照上圖,需要三字節(jié)表示抢呆。
?格式是:1110xxxx 10xxxxxx 10xxxxxx
0x6c49轉(zhuǎn)為二進(jìn)制:110110001001001
從地位依次填充(高位補(bǔ)零):? 11100110 10110001 10001001
轉(zhuǎn)為十六進(jìn)制(UTF-8):0xE6 B189
譯碼時(shí):有多少個(gè)1就代表是多少個(gè)字節(jié)(N個(gè)后由一個(gè)0隔開(kāi))
?
UTF-16:
平面的概念:unicode將全世界所有的字符定義在一個(gè)集合里,這么多字符不是一次性定義的笛谦,而是分區(qū)定義抱虐。每個(gè)區(qū)可以存放65535個(gè)(2^16)字符,稱為一個(gè)平面饥脑。目前共使用了17(2^4+1)個(gè)平面恳邀。
基本平面的碼點(diǎn)范圍:0x0000-0xffff? ,都采用兩字節(jié)存儲(chǔ),因此不兼容ASCII碼
輔助平面的碼點(diǎn)范圍:0x010000-0x10ffff<2^5>
編碼規(guī)定:
???? 基本平面占用兩字節(jié)灶轰,輔助平面占用四字節(jié)谣沸。
同樣的問(wèn)題:
???? 譯碼時(shí)怎么區(qū)分兩字節(jié)和四字節(jié)字符呢?
在這里使用了另外一種方法:
在基本平面內(nèi)設(shè)置了一個(gè)空段:0xD800-0xDFFF笋颤,這2^11空間分為兩部分乳附,D8000到? ? DBFF(共2^10空間)稱為高位,DC00到DFFF稱為底位伴澄,為什么要這么稱呼呢赋除?
UTF-16把超出基本平面部分的字節(jié)分高低位(高8位,底8位)非凌,然后分別映射(從地位開(kāi)始復(fù)制举农,多余位不動(dòng))到剛說(shuō)的基本平面的空段的高低位(高位補(bǔ)零)
?Eg:
???? 漢子“?”的unicode碼點(diǎn)為0x20BB7
基本平面存儲(chǔ)為0xffff
超出部分為0x20BB7-0x10000=10BB7
轉(zhuǎn)為二進(jìn)制:100001011 10110111
補(bǔ)齊20位:0001000010 1110110111
映射:
0001000010(高十位)-> 0XD800(1101101100000000)? :? 1101100001000010轉(zhuǎn)十六進(jìn)制:D842
?1110110111(底十位) ->0xDC00(1101110000000000)? :? 1101111110110111轉(zhuǎn)十六進(jìn)制:DFB7
得到漢字“敞嗡?”的UTF-16編碼為0xD842 0xDFB7
? 輔助平面轉(zhuǎn)換公式:
? ?H = ( num– 0x10000) / 0x400) + 0xD800
? ?L = ( num– 0x10000) % 0x400) + 0xDC00
UTF-8是對(duì)多字符進(jìn)行標(biāo)記颁糟,不固定長(zhǎng)度存儲(chǔ)從而節(jié)省空間
UTF-16,小于兩字節(jié)長(zhǎng)度的字符固定兩字節(jié)長(zhǎng)度存儲(chǔ)喉悴,超出就按四字節(jié)存儲(chǔ)棱貌,而四字節(jié)分為高低位映射到前兩字節(jié)存儲(chǔ),也就是只用了兩字節(jié)空間
總結(jié):
??? Unicode是一種可以在計(jì)算機(jī)上使用的字符編碼粥惧,它為每一種語(yǔ)言每一個(gè)字符都設(shè)定了一個(gè)二進(jìn)制編碼键畴,以滿足跨語(yǔ)言、跨平臺(tái)進(jìn)行文本轉(zhuǎn)換、處理的要求起惕。使用數(shù)字0-0x10FFFF映射字符涡贱,最多容納1114112個(gè)字符(的17個(gè)平面大小2^16*17,其中有已經(jīng)使用的平面惹想,也有備用平面或者給用戶自定義字符平面等)问词。
UTF-8、UTF-16嘀粱、UTF-32是對(duì)Unicode字符集不同的編碼方式激挪,比如漢字“字”在unicode中對(duì)應(yīng)的數(shù)字是23383,把其按照不同的編碼方式轉(zhuǎn)換為程序數(shù)據(jù)如下:(無(wú)符號(hào))
UTF-8:0xE6,0xB1,0x89,0xAD,0x97
UTF-16:0x6C49,0x5B57