Unicode与UTF-8的区别
轉(zhuǎn)載自??Unicode與UTF-8的區(qū)別
要弄清Unicode與UTF-8的關(guān)系,我們還得從他們的來源說起,下來我們從剛開始的編碼說起,直到Unicode的出現(xiàn),我們就會(huì)感覺到他們之間的關(guān)系?
ASCII碼
我們都知道,在計(jì)算機(jī)的世界里,信息的表示方式只有0和1,但是我們?nèi)祟愋畔⒈硎镜姆绞絽s與之大不相同,很多時(shí)候是用語言文字、圖像、聲音等傳遞信息的。
那么我們?cè)鯓訉⑵滢D(zhuǎn)化為二進(jìn)制存儲(chǔ)到計(jì)算機(jī)中,這個(gè)過程我們稱之為編碼。更廣義地講就是把信息從一種形式轉(zhuǎn)化為另一種形式的過程。?
我們知道一個(gè)二進(jìn)制有兩種狀態(tài):”0” 狀態(tài) 和 “1”狀態(tài),那么它就可以代表兩種不同的東西,我們想賦予它什么含義,就賦予什么含義,比如說我規(guī)定,“0” 代表 “吃過了”, “1”代表 “還沒吃”。
這樣,我們就相當(dāng)于把現(xiàn)實(shí)生活中的信息編碼成二進(jìn)制數(shù)字了,并且這個(gè)例子中是一位二進(jìn)制數(shù)字,那么2位二進(jìn)制數(shù)可以代表多少種情況能?對(duì),是四種,2^2,分別是 00、01、10、11,那7種呢?答案是2^7=128。
我們知道,在計(jì)算機(jī)中每八個(gè)二進(jìn)制位組成了一個(gè)字節(jié)(Byte),計(jì)算機(jī)存儲(chǔ)的最小單位就是字節(jié),字節(jié)如下圖所示?:
?
所以早期人們用8位二進(jìn)制來編碼英文字母(最前面的一位是0),也就是說,將英文字母和一些常用的字符和這128中二進(jìn)制0、1串一一對(duì)應(yīng)起來,比如說 大寫字母“A”所對(duì)應(yīng)的二進(jìn)制位“01000001”,轉(zhuǎn)換為十六進(jìn)制為41。
在美國(guó),這128是夠了,但是其他國(guó)家不答應(yīng)啊,他們的字符和英文是有出入的,比如在法語中在字母上有注音符號(hào),如?é?,這個(gè)怎么表示成二進(jìn)制?
所以各個(gè)國(guó)家就決定把字節(jié)中最前面未使用的那一個(gè)位拿來使用,原來的128種狀態(tài)就變成了256種狀態(tài),比如é就被編碼成130(二進(jìn)制的10000010)。
為了保持與ASCII碼的兼容性,一般最高為為0時(shí)和原來的ASCII碼相同,最高位為1的時(shí)候,各個(gè)國(guó)家自己給后面的位(1xxx xxxx)賦予他們國(guó)家的字符意義。
但是這樣一來又有問題出現(xiàn)了,不同國(guó)家對(duì)新增的128個(gè)數(shù)字賦予了不同的含義,比如說130在法語中代表了é,但是在希伯來語中卻代表了字母Gimel(這不是希伯來字母,只是讀音翻譯成英文的形式)具體的希伯來字母Gimel看下圖?
?
所以這就成了不同國(guó)家有不同國(guó)家的編碼方式,所以如果給你一串二進(jìn)制數(shù),你想要解碼,就必須知道它的編碼方式,不然就會(huì)出現(xiàn)我們有時(shí)候看到的亂碼?。
?
Unicode的出現(xiàn)
Unicode為世界上所有字符都分配了一個(gè)唯一的數(shù)字編號(hào),這個(gè)編號(hào)范圍從?0x000000 到 0x10FFFF(十六進(jìn)制),有110多萬,每個(gè)字符都有一個(gè)唯一的Unicode編號(hào),這個(gè)編號(hào)一般寫成16進(jìn)制,在前面加上U+。例如:“馬”的Unicode是U+9A6C。
Unicode就相當(dāng)于一張表,建立了字符與編號(hào)之間的聯(lián)系
?
它是一種規(guī)定,Unicode本身只規(guī)定了每個(gè)字符的數(shù)字編號(hào)是多少,并沒有規(guī)定這個(gè)編號(hào)如何存儲(chǔ)。
有的人會(huì)說了,那我可以直接把Unicode編號(hào)直接轉(zhuǎn)換成二進(jìn)制進(jìn)行存儲(chǔ),是的,你可以,但是這個(gè)就需要人為的規(guī)定了,而Unicode并沒有說這樣弄,因?yàn)槌四氵@種直接轉(zhuǎn)換成二進(jìn)制的方案外,還有其他方案,接下來我們會(huì)逐一看到。?
編號(hào)怎么對(duì)應(yīng)到二進(jìn)制表示呢?有多種方案:主要有UTF-8,UTF-16,UTF-32。
1、UTF-32?
先來看簡(jiǎn)單的UTF-32?
這個(gè)就是字符所對(duì)應(yīng)編號(hào)的整數(shù)二進(jìn)制形式,四個(gè)字節(jié)。這個(gè)就是直接轉(zhuǎn)換。 比如馬的Unicode為:U+9A6C,那么直接轉(zhuǎn)化為二進(jìn)制,它的表示就為:1001 1010 0110 1100。
這里需要說明的是,轉(zhuǎn)換成二進(jìn)制后計(jì)算機(jī)存儲(chǔ)的問題,我們知道,計(jì)算機(jī)在存儲(chǔ)器中排列字節(jié)有兩種方式:大端法和小端法,大端法就是將高位字節(jié)放到底地址處,比如0x1234, 計(jì)算機(jī)用兩個(gè)字節(jié)存儲(chǔ),一個(gè)是高位字節(jié)0x12,一個(gè)是低位字節(jié)0x34,它的存儲(chǔ)方式為下:
?
UTF-32用四個(gè)字節(jié)表示,處理單元為四個(gè)字節(jié)(一次拿到四個(gè)字節(jié)進(jìn)行處理),如果不分大小端的話,那么就會(huì)出現(xiàn)解讀錯(cuò)誤,比如我們一次要處理四個(gè)字節(jié) 12 34 56 78,這四個(gè)字節(jié)是表示0x12 34 56 78還是表示0x78 56 34 12 ?不同的解釋最終表示的值不一樣。
我們可以根據(jù)他們高低字節(jié)的存儲(chǔ)位置來判斷他們所代表的含義,所以在編碼方式中有UTF-32BE和UTF-32LE,分別對(duì)應(yīng)大端和小端,來正確地解釋多個(gè)字節(jié)(這里是四個(gè)字節(jié))的含義。
?
2、UTF-16?
UTF-16使用變長(zhǎng)字節(jié)表示?
① 對(duì)于編號(hào)在U+0000到U+FFFF的字符(常用字符集),直接用兩個(gè)字節(jié)表示。?
② 編號(hào)在?U+10000到U+10FFFF之間的字符,需要用四個(gè)字節(jié)表示。
同樣,UTF-16 也有字節(jié)的順序問題(大小端),所以就有UTF-16BE表示大端,UTF-16LE表示小端。
?
3、UTF-8?
UTF-8就是使用變長(zhǎng)字節(jié)表示,顧名思義,就是使用的字節(jié)數(shù)可變,這個(gè)變化是根據(jù)Unicode編號(hào)的大小有關(guān),編號(hào)小的使用的字節(jié)就少,編號(hào)大的使用的字節(jié)就多。使用的字節(jié)個(gè)數(shù)從1到4個(gè)不等。
UTF-8的編碼規(guī)則是:
①?對(duì)于單字節(jié)的符號(hào),字節(jié)的第一位設(shè)為0,后面的7位為這個(gè)符號(hào)的Unicode碼,因此對(duì)于英文字母,UTF-8編碼和ASCII碼是相同的。?
②?對(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碼 。
舉個(gè)例子:比如說一個(gè)字符的Unicode編碼是130,顯然按照UTF-8的規(guī)則一個(gè)字節(jié)是表示不了它(因?yàn)槿绻且粋€(gè)字節(jié)的話前面的一位必須是0),所以需要兩個(gè)字節(jié)(n = 2)。
根據(jù)規(guī)則,第一個(gè)字節(jié)的前 2 位都設(shè)為1,第3(2+1)位設(shè)為0,則第一個(gè)字節(jié)為:110X XXXX,后面字節(jié)的前兩位一律設(shè)為10,后面只剩下一個(gè)字節(jié),所以后面的字節(jié)為:10XX XXXX。
所以它的格式為110XXXXX?10XXXXXX 。
下面我們來具體看看具體的Unicode編號(hào)范圍與對(duì)應(yīng)的UTF-8二進(jìn)制格式?
?
那么對(duì)于一個(gè)具體的Unicode編號(hào),具體怎么進(jìn)行UTF-8的編碼呢?
首先找到該Unicode編號(hào)所在的編號(hào)范圍,進(jìn)而可以找到與之對(duì)應(yīng)的二進(jìn)制格式,然后將該Unicode編號(hào)轉(zhuǎn)化為二進(jìn)制數(shù)(去掉高位的0),最后將該二進(jìn)制數(shù)從右向左依次填入二進(jìn)制格式的X中,如果還有X未填,則設(shè)為0 。
比如:“馬”的Unicode編號(hào)是:0x9A6C,整數(shù)編號(hào)是39532,對(duì)應(yīng)第三個(gè)范圍(2048 - 65535),其格式為:1110XXXX 10XXXXXX 10XXXXXX,39532?對(duì)應(yīng)的二進(jìn)制是?1001 1010 0110 1100,將二進(jìn)制填入進(jìn)入就為:?
11101001?10101001?10101100?。
?
?
由于UTF-8的處理單元為一個(gè)字節(jié)(也就是一次處理一個(gè)字節(jié)),所以處理器在處理的時(shí)候就不需要考慮這一個(gè)字節(jié)的存儲(chǔ)是在高位還是在低位,直接拿到這個(gè)字節(jié)進(jìn)行處理就行了,因?yàn)榇笮《耸轻槍?duì)大于一個(gè)字節(jié)的數(shù)的存儲(chǔ)問題而言的。
綜上所述,UTF-8、UTF-16、UTF-32都是Unicode的一種實(shí)現(xiàn)。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Unicode与UTF-8的区别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人情练达即文章上一句是什么 给大家介绍一
- 下一篇: 10亿个数中找出最大的10000个数