Unicode
Unicode 是一種編碼雕凹,它將世界上所有的符號(hào)都納入其中。每一個(gè)符號(hào)都給予一個(gè)獨(dú)一無二的編碼政冻。這樣亂碼問題就會(huì)消失枚抵。這就是 Unicode,就像它的名字都表示的明场,這是一種所有符號(hào)的編碼汽摹。
Unicode 是一個(gè)很大的集合,現(xiàn)在的規(guī)目嘞牵可以容納100多萬個(gè)符號(hào)逼泣。每個(gè)符號(hào)的編碼都不一樣趴泌。
Unicode問題
Unicode 只是一個(gè)符號(hào)集,它只規(guī)定了符號(hào)的二進(jìn)制代碼拉庶,卻沒有規(guī)定這個(gè)二進(jìn)制代碼應(yīng)該如何存儲(chǔ)嗜憔。
比如,漢字“ 金 ”的 Unicode 是十六進(jìn)制數(shù)91D5氏仗,轉(zhuǎn)換成二進(jìn)制數(shù)足足有15位( 1001 0001 1101 0001)吉捶,也就是說,這個(gè)符號(hào)的表示至少需要2個(gè)字節(jié)皆尔。表示其他更大的符號(hào)呐舔,可能需要3個(gè)字節(jié)或者4個(gè)字節(jié),甚至更多床佳。
這里就有兩個(gè)嚴(yán)重的問題:
第一個(gè)問題是:如何才能區(qū)別 Unicode 和 ASCII 滋早?計(jì)算機(jī)怎么知道三個(gè)字節(jié)表示一個(gè)符號(hào),而不是分別表示三個(gè)符號(hào)呢砌们? 比如這個(gè)“金”字杆麸, 二進(jìn)制是 1001 0001 1101 0001 我們?cè)趺粗浪皇莾蓚€(gè)ascii 字符, 分別是10010001 和 11010001 浪感? 而是1001000111010001一個(gè)整體表示一個(gè)字符昔头?
所以就有這個(gè)問題, unicode 雖然定義了每個(gè)字符的唯一二進(jìn)制編碼影兽, 但是那里是分隔符我們不確定揭斧, 我們不知道到底哪里是代表一個(gè)字符,還是兩個(gè)字符峻堰,或者三個(gè)字符讹开。所以必須有一些規(guī)則來定義這個(gè)分割符第二個(gè)問題是,有了第一個(gè)問題捐名,我們很自然會(huì)想到旦万, 自然沒法區(qū)分怎么分割字符,那么干脆每個(gè)字符都用三個(gè)字節(jié)代表吧镶蹋, 每三個(gè)字節(jié)就是一個(gè)字符成艘, 一刀切,最妥當(dāng)了贺归。
但是我們已經(jīng)知道淆两,英文字母只用一個(gè)字節(jié)表示就夠了,如果 Unicode 統(tǒng)一規(guī)定拂酣,每個(gè)符號(hào)用三個(gè)或四個(gè)字節(jié)表示秋冰,那么每個(gè)英文字母前都必然有二到三個(gè)字節(jié)是0,這對(duì)于存儲(chǔ)來說是極大的浪費(fèi)婶熬,文本文件的大小會(huì)因此大出二三倍剑勾,這是無法接受的光坝。
UTF-8
互聯(lián)網(wǎng)的普及,強(qiáng)烈要求出現(xiàn)一種統(tǒng)一的編碼方式甥材。UTF-8 就是在互聯(lián)網(wǎng)上使用最廣的一種 Unicode 的實(shí)現(xiàn)方式盯另。重復(fù)一遍,這里的關(guān)系是洲赵,UTF-8 是 Unicode 的實(shí)現(xiàn)方式之一鸳惯。
UTF-8 最大的一個(gè)特點(diǎn),就是它是一種變長的編碼方式叠萍。它可以使用1~4個(gè)字節(jié)表示一個(gè)符號(hào)芝发,根據(jù)不同的符號(hào)而變化字節(jié)長度。
UTF-8 的編碼規(guī)則很簡單苛谷,只有二條:
1)對(duì)于單字節(jié)的符號(hào)辅鲸,字節(jié)的第一位設(shè)為0,后面7位為這個(gè)符號(hào)的 Unicode 碼腹殿。因此對(duì)于英語字母独悴,UTF-8 編碼和 ASCII 碼是相同的。
2)對(duì)于n字節(jié)的符號(hào)(n > 1)锣尉,第一個(gè)字節(jié)的前n位都設(shè)為1刻炒,第n + 1位設(shè)為0,后面字節(jié)的前兩位一律設(shè)為10自沧。剩下的沒有提及的二進(jìn)制位坟奥,全部為這個(gè)符號(hào)的 Unicode 碼。
下表總結(jié)了編碼規(guī)則拇厢,字母x表示可用編碼的位爱谁。
Unicode符號(hào)范圍 | UTF-8編碼方式
(十六進(jìn)制) | (二進(jìn)制)
----------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
跟據(jù)上表,解讀 UTF-8 編碼非常簡單孝偎。如果一個(gè)字節(jié)的第一位是0访敌,則這個(gè)字節(jié)單獨(dú)就是一個(gè)字符;如果第一位是1邪媳,則連續(xù)有多少個(gè)1捐顷,就表示當(dāng)前字符占用多少個(gè)字節(jié)荡陷。
還是以金
字來講解雨效, 金
的unicode碼是91D1(16進(jìn)制), 對(duì)應(yīng)的二進(jìn)制是: 1001 0001 1101 0001(二進(jìn)制)废赞,它在unicode的第三個(gè)范圍徽龟,0000 0800-0000 FFFF , 所以如果它要用utf-8來表示的話唉地, 就要按找utf-8定義的規(guī)則 1110xxxx 10xxxxxx 10xxxxxx
來轉(zhuǎn)成utf-8的編碼据悔。
最后轉(zhuǎn)換的UTF-8結(jié)果就是:11101001 10000111 10010001
而這個(gè)UTF-8的碼是二進(jìn)制的传透,轉(zhuǎn)成16進(jìn)制就是 e9 87 91 (十六進(jìn)制)
然后轉(zhuǎn)成我們平常python 打印字符時(shí)候顯示的UTF-8字符 \xe9\x87\91
\x是個(gè)分隔符。
UTF-8 GBK UTF8 GB2312 之間的區(qū)別和關(guān)系
UTF-8:Unicode TransformationFormat-8bit极颓,允許含BOM朱盐,但通常不含BOM。是用以解決國際上字符的一種多字節(jié)編碼菠隆,它對(duì)英文使用8位(即一個(gè)字節(jié))兵琳,中文使用24為(三個(gè)字節(jié))來編碼。UTF-8包含全世界所有國家需要用到的字符骇径,是國際編碼躯肌,通用性強(qiáng)。UTF-8編碼的文字可以在各國支持UTF8字符集的瀏覽器上顯示破衔。如清女,如果是UTF8編碼,則在外國人的英文IE上也能顯示中文晰筛,他們無需下載IE的中文語言支持包嫡丙。
GBK是國家標(biāo)準(zhǔn)GB2312基礎(chǔ)上擴(kuò)容后兼容GB2312的標(biāo)準(zhǔn)。GBK的文字編碼是用雙字節(jié)來表示的读第,即不論中迄沫、英文字符均使用雙字節(jié)來表示,為了區(qū)分中文卦方,將其最高位都設(shè)定成1羊瘩。GBK包含全部中文字符,是國家編碼盼砍,通用性比UTF8差尘吗,不過UTF8占用的數(shù)據(jù)庫比GBD大。
GBK浇坐、GB2312等與UTF8之間都必須通過Unicode編碼才能相互轉(zhuǎn)換:
GBK睬捶、GB2312--Unicode--UTF8
UTF8--Unicode--GBK、GB2312
因?yàn)閡nicode 定義所有字符都有唯一的二進(jìn)制近刘, 所以任何的編碼轉(zhuǎn)換都要轉(zhuǎn)成unicode作為中介擒贸,然后再根據(jù)各個(gè)編碼規(guī)則,自己轉(zhuǎn)成自己的編碼
總結(jié)
unicode 金
轉(zhuǎn)成utf-8 步驟 :
1.查詢到金
的unicode 是 91d1
2.91d1
在unicode符號(hào)范圍 0000 0800-0000 FFFF
里面觉渴, 對(duì)應(yīng)的utf-8規(guī)則是 1110xxxx 10xxxxxx 10xxxxxx
3.91d1
轉(zhuǎn)成二進(jìn)制是: 10010001 11010001
4.然后將91d1
的二進(jìn)制 10010001 11010001
按規(guī)則轉(zhuǎn)成utf-8的 11101001 1000 0111 1001 0001
5.utf-8的二進(jìn)制 11101001 1000 0111 1001 0001
轉(zhuǎn)成 utf-8的十六進(jìn)制是 e1 87 91
6.所以最后金
utf-8字符就是 \xe1\x87\x91