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