字符編碼問(wèn)題從之前學(xué)Python的時(shí)候就開(kāi)始困擾我磁玉,一直沒(méi)有去理清楚Unicode和UTF-8之間是什么關(guān)系抽莱,只知道在寫(xiě)代碼的時(shí)候要不斷的decode鸦泳、encode不停的轉(zhuǎn)換才能避免各種奇怪的亂碼船老。前兩天在學(xué)習(xí)Go的時(shí)候又碰到了關(guān)于字符的問(wèn)題,就花時(shí)間將它理清滚躯,繪制了幾個(gè)圖幫助理解雏门,發(fā)現(xiàn)好像也并沒(méi)有那么復(fù)雜
字符編碼
1. Unicode與UTF-8的誕生
? a. 簡(jiǎn)單介紹下字符編碼:在計(jì)算機(jī)中所有內(nèi)容都是以二進(jìn)制存儲(chǔ),那么該如何表示字符呢掸掏?其實(shí)就是制作一個(gè)“映射表”剿配,例如使用二進(jìn)制(01000001)表示大寫(xiě)字母A,將不同的字母阅束、符號(hào)分別用一個(gè)值表示呼胚。計(jì)算機(jī)在讀到一串字節(jié)流的時(shí)候,去這張表中查找息裸,再將它轉(zhuǎn)換成對(duì)應(yīng)的字母蝇更、符號(hào)即可。而因?yàn)橛⑽淖帜讣臃?hào)數(shù)量并不多呼盆,使用8個(gè)二進(jìn)制位就完全足以表示年扩,ASCII碼就是這樣。
? b. 后來(lái)計(jì)算機(jī)不斷的發(fā)展访圃,除了美國(guó)厨幻,其他國(guó)家的人也希望用計(jì)算機(jī)。英語(yǔ)用128個(gè)符號(hào)編碼就夠了腿时,但是用來(lái)表示其他語(yǔ)言况脆,128個(gè)符號(hào)是不夠的。ASCII顯然無(wú)法滿(mǎn)足其他語(yǔ)言的需求批糟。于是不同國(guó)家就開(kāi)始使用不同的編碼方式格了,這樣就導(dǎo)致不同國(guó)家的人“交流”十分困難,因?yàn)榫幋a方式不同而經(jīng)常導(dǎo)致亂碼
? c. 為了解決這一問(wèn)題徽鼎,人們將將所有的語(yǔ)言符號(hào)放到一個(gè)集合中盛末,每一個(gè)符號(hào)用唯一的一個(gè)編碼標(biāo)識(shí),這就是Unicode否淤。所以悄但,Unicode本質(zhì)上是一個(gè)字符集合。
? d. Unicode存在的問(wèn)題:
? (1)它只規(guī)定了每個(gè)字符的一個(gè)唯一標(biāo)識(shí)-- 一個(gè)二進(jìn)制代碼石抡,但是沒(méi)有規(guī)定這個(gè)標(biāo)識(shí)該怎么存儲(chǔ)檐嚣。比如說(shuō)靠前 面的字符這個(gè)標(biāo)識(shí)比較小,只需一個(gè)字節(jié)即可存儲(chǔ)汁雷;而靠后面的這個(gè)代碼較大净嘀,需要多個(gè)字節(jié)存儲(chǔ)。若統(tǒng)一規(guī)定所有 的字符使用三個(gè)或四個(gè)字節(jié)存儲(chǔ)侠讯,則會(huì)造成巨大的浪費(fèi)挖藏。
? (2) 沒(méi)有規(guī)定一個(gè)編碼方案。比如字節(jié)流傳來(lái)三個(gè)字節(jié)厢漩,那么該如何識(shí)別膜眠?它有可能是三個(gè)字符、兩個(gè)字符溜嗜、 一個(gè)字符宵膨,具有多種情況,計(jì)算機(jī)該怎么識(shí)別炸宵?
? e. UTF-8的誕生
? (1) 上面說(shuō)到辟躏,Unicode作為一個(gè)字符集,存在著資源浪費(fèi)和字節(jié)流識(shí)別字符兩個(gè)尚未解決的問(wèn)題土全,那么就需 要一種編碼方式能夠解決這樣的問(wèn)題捎琐。UTF-8就這樣誕生了。
? (2)UTF-8的編碼規(guī)則:
1)對(duì)于單字節(jié)的符號(hào)裹匙,字節(jié)的第一位設(shè)為
0
瑞凑,后面7位為這個(gè)符號(hào)的 Unicode 碼。因此對(duì)于英語(yǔ)字母概页,UTF-8 編碼和 ASCII 碼是相同的籽御。2)對(duì)于
n
字節(jié)的符號(hào)(n > 1
),第一個(gè)字節(jié)的前n
位都設(shè)為1
惰匙,第n + 1
位設(shè)為0
技掏,后面字節(jié)的前兩位一律設(shè)為10
。剩下的沒(méi)有提及的二進(jìn)制位项鬼,全部為這個(gè)符號(hào)的 Unicode 碼零截。
? (3) 從UTF-8的編碼規(guī)則可以看出:UTF-8是一種可變長(zhǎng)編碼,避免了資源浪費(fèi)的同時(shí)也解決了字節(jié)流的識(shí) 別問(wèn)題秃臣,因此涧衙,目前使用最廣的就是UTF-8編碼了。
? f. 其他Unicode編碼方式:常見(jiàn)的有UCS-2/UTF-16奥此、GB18030等弧哎,這里就不再敘述。
2. 編碼與解碼具體過(guò)程
? a. 編碼:將字符轉(zhuǎn)成字節(jié)流稚虎,直接用圖說(shuō)明編碼的過(guò)程
?
? b. 解碼:將字節(jié)流轉(zhuǎn)換成字符撤嫩,下面上圖:
?
? c. 不同編碼之間的轉(zhuǎn)換:
更多文章發(fā)布在我的個(gè)人博客上,歡迎訪問(wèn)
www.guiguiyo.cn