Unicode、UTF-8担神、ASCII都是啥?區(qū)別和聯(lián)系孩锡?

字符串是一種數(shù)據(jù)類型炕置,但是朴摊,字符串比較特殊的是還有一個(gè)編碼問(wèn)題。
因?yàn)橛?jì)算機(jī)只能處理數(shù)字鹃操,如果要處理文本赴背,就必須先把文本轉(zhuǎn)換為數(shù)字才能處理耸三。

計(jì)算機(jī)中儲(chǔ)存的信息都是用二進(jìn)制數(shù)表示的仪壮;我們?cè)谄聊簧峡吹降挠⑽摹h字等字符是二進(jìn)制數(shù)轉(zhuǎn)換之后的結(jié)果缚陷。通俗的說(shuō),按照何種規(guī)則將字符存儲(chǔ)在計(jì)算機(jī)中虎锚,如'a'用什么表示非春,稱為"編碼"护侮;反之凳忙,將存儲(chǔ)在計(jì)算機(jī)中的二進(jìn)制數(shù)解析顯示出來(lái),稱為"解碼"柳恐,如同密碼學(xué)中的加密和解密。

ASCII:

每一個(gè)二進(jìn)制位(bit)有0和1兩種狀態(tài)乐设,因此八個(gè)二進(jìn)制位就可以組合出256種狀態(tài),這被稱為一個(gè)字節(jié)(byte)近尚。也就是說(shuō),一個(gè)字節(jié)一共可以用來(lái)表示256種不同的狀態(tài)戈锻,每一個(gè)狀態(tài)對(duì)應(yīng)一個(gè)符號(hào),就是256個(gè)符號(hào)格遭,從00000000到11111111哈街。

上個(gè)世紀(jì)60年代拒迅,美國(guó)制定了一套字符編碼,對(duì)英語(yǔ)字符與二進(jìn)制位之間的關(guān)系璧微,做了統(tǒng)一規(guī)定。這被稱為 ASCII 碼往毡,一直沿用至今。比如大寫字母A的編碼是65开瞭,小寫字母z的編碼是122。

ASCII 碼一共規(guī)定了128個(gè)字符的編碼嗤详,比如空格SPACE是32(二進(jìn)制00100000),大寫的字母A是65(二進(jìn)制01000001)葱色。這128個(gè)符號(hào)(包括32個(gè)不能打印出來(lái)的控制符號(hào)),只占用了一個(gè)字節(jié)的后面7位苍狰,最前面的一位統(tǒng)一規(guī)定為0。


ASCII(表一)

非 ASCII 編碼

英語(yǔ)用128個(gè)符號(hào)編碼就夠了淋昭,但是用來(lái)表示其他語(yǔ)言,128個(gè)符號(hào)是不夠的翔忽。比如盏檐,在法語(yǔ)中驶悟,字母上方有注音符號(hào)胡野,它就無(wú)法用 ASCII 碼表示痕鳍。于是,一些歐洲國(guó)家就決定笼呆,利用字節(jié)中閑置的最高位編入新的符號(hào)。比如抄邀,法語(yǔ)中的é的編碼為130(二進(jìn)制10000010)昼榛。這樣一來(lái)境肾,這些歐洲國(guó)家使用的編碼體系胆屿,可以表示最多256個(gè)符號(hào)。

ASCII擴(kuò)展表(表二)

但是非迹,這里又出現(xiàn)了新的問(wèn)題。不同的國(guó)家有不同的字母憎兽,因此,哪怕它們都使用256個(gè)符號(hào)的編碼方式纯命,代表的字母卻不一樣。比如亿汞,130在法語(yǔ)編碼中代表了é,在希伯來(lái)語(yǔ)編碼中卻代表了字母Gimel (?)疗我,在俄語(yǔ)編碼中又會(huì)代表另一個(gè)符號(hào)。但是不管怎樣吴裤,所有這些編碼方式中,0--127表示的符號(hào)是一樣的嚼摩,不一樣的只是128--255的這一段矿瘦。

至于亞洲國(guó)家的文字,使用的符號(hào)就更多了缚去,漢字就多達(dá)10萬(wàn)左右。一個(gè)字節(jié)只能表示256種符號(hào)易结,肯定是不夠的,就必須使用多個(gè)字節(jié)表達(dá)一個(gè)符號(hào)搞动,而且還不能和ASCII編碼沖突,所以鹦肿,中國(guó)制定了GB2312編碼,用來(lái)把中文編進(jìn)去箩溃。(GB2312采用2個(gè)字節(jié),理論上最多可以表示 256 x 256 = 65536 個(gè)符號(hào))

Unicode

你可以想得到的是涣旨,全世界有上百種語(yǔ)言,日本把日文編到Shift_JIS里霹陡,韓國(guó)把韓文編到Euc-kr里。要想打開(kāi)一個(gè)文本文件烹棉,就必須知道它的編碼方式,否則用錯(cuò)誤的編碼方式解讀峦耘,就會(huì)出現(xiàn)亂碼。另外旅薄,各國(guó)有各國(guó)的標(biāo)準(zhǔn),就會(huì)不可避免地出現(xiàn)沖突洛口,在多語(yǔ)言混合的文本中,顯示出來(lái)會(huì)有亂碼第焰。

如果有一種編碼,將世界上所有的符號(hào)都納入其中妨马。每一個(gè)符號(hào)都給予一個(gè)獨(dú)一無(wú)二的編碼杀赢,那么亂碼問(wèn)題就會(huì)消失湘纵。這就是 Unicode脂崔,就像它的名字都表示的梧喷,這是一種所有符號(hào)的編碼。

Unicode標(biāo)準(zhǔn)也在不斷發(fā)展铺敌,但最常用的是用兩個(gè)字節(jié)表示一個(gè)字符(如果要用到非常偏僻的字符,就需要4個(gè)字節(jié))〕テ荆現(xiàn)代操作系統(tǒng)和大多數(shù)編程語(yǔ)言都直接支持Unicode。

Unicode 當(dāng)然是一個(gè)很大的集合弯囊,現(xiàn)在的規(guī)模可以容納100多萬(wàn)個(gè)符號(hào)常挚。每個(gè)符號(hào)的編碼都不一樣稽物,比如奄毡,U+0639表示阿拉伯字母"Ain"贝或,U+0041表示英語(yǔ)的大寫字母"A",U+4E25表示漢字"嚴(yán)"咪奖。具體的符號(hào)對(duì)應(yīng)表,漢文查詢表羊赵。

需要注意的是,Unicode 只是一個(gè)符號(hào)集昧捷,它只規(guī)定了符號(hào)的二進(jìn)制代碼,卻沒(méi)有規(guī)定這個(gè)二進(jìn)制代碼應(yīng)該如何存儲(chǔ)靡挥。

比如,漢字"嚴(yán)"的 Unicode 是十六進(jìn)制數(shù)4E25跋破,轉(zhuǎn)換成二進(jìn)制數(shù)足足有15位(100111000100101)瓶蝴,也就是說(shuō),這個(gè)符號(hào)的表示至少需要2個(gè)字節(jié)舷手。表示其他更大的符號(hào)令蛉,可能需要3個(gè)字節(jié)或者4個(gè)字節(jié)聚霜,甚至更多珠叔。

這里就有兩個(gè)嚴(yán)重的問(wèn)題:

  • 如何才能區(qū)別 Unicode 和 ASCII ?計(jì)算機(jī)怎么知道三個(gè)字節(jié)表示一個(gè)符號(hào)祷安,而不是分別表示三個(gè)符號(hào)呢?
  • 第二個(gè)問(wèn)題是汇鞭,我們已經(jīng)知道,英文字母只用一個(gè)字節(jié)表示就夠了霍骄,如果 Unicode 統(tǒng)一規(guī)定,每個(gè)符號(hào)用三個(gè)或四個(gè)字節(jié)表示读整,那么每個(gè)英文字母前都必然有二到三個(gè)字節(jié)是0,這對(duì)于存儲(chǔ)來(lái)說(shuō)是極大的浪費(fèi)米间,文本文件的大小會(huì)因此大出二三倍,這是無(wú)法接受的屈糊。

它們?cè)斐傻慕Y(jié)果是:1)出現(xiàn)了 Unicode 的多種存儲(chǔ)方式,也就是說(shuō)有許多種不同的二進(jìn)制格式逻锐,可以用來(lái)表示 Unicode。2)Unicode 在很長(zhǎng)一段時(shí)間內(nèi)無(wú)法推廣昧诱,直到互聯(lián)網(wǎng)的出現(xiàn)。

UTF-8

互聯(lián)網(wǎng)的普及鳄哭,強(qiáng)烈要求出現(xiàn)一種統(tǒng)一的編碼方式。UTF-8 就是在互聯(lián)網(wǎng)上使用最廣的一種 Unicode 的實(shí)現(xiàn)方式。其他實(shí)現(xiàn)方式還包括 UTF-16(字符用兩個(gè)字節(jié)或四個(gè)字節(jié)表示)和 UTF-32(字符用四個(gè)字節(jié)表示)局劲,不過(guò)在互聯(lián)網(wǎng)上基本不用。重復(fù)一遍鱼填,這里的關(guān)系是,UTF-8 是 Unicode 的實(shí)現(xiàn)方式之一苹丸。

UTF-8 最大的一個(gè)特點(diǎn),就是它是一種變長(zhǎng)的編碼方式赘理。它可以使用1~4個(gè)字節(jié)表示一個(gè)符號(hào),根據(jù)不同的符號(hào)而變化字節(jié)長(zhǎng)度商模。

UTF-8 的編碼規(guī)則很簡(jiǎn)單,只有兩條:

1)對(duì)于單字節(jié)的符號(hào):字節(jié)的第一位設(shè)為0施流,后面7位為這個(gè)符號(hào)的 Unicode 碼。因此對(duì)于英語(yǔ)字母瞪醋,UTF-8 編碼和 ASCII 碼是相同的;(即趟章,ASCII編碼實(shí)際上可以被看成是UTF-8編碼的一部分,所以,大量只支持ASCII編碼的歷史遺留軟件可以在UTF-8編碼下繼續(xù)工作宏侍。)
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 碼。

UTF-8編碼規(guī)則

跟據(jù)上表褂始,解讀 UTF-8 編碼非常簡(jiǎn)單。如果一個(gè)字節(jié)的第一位是0崎苗,則這個(gè)字節(jié)單獨(dú)就是一個(gè)字符舀寓;如果第一位是1,則連續(xù)有多少個(gè)1互墓,就表示當(dāng)前字符占用多少個(gè)字節(jié)。

下面篡撵,還是以漢字“嚴(yán)”為例,演示如何實(shí)現(xiàn) UTF-8 編碼育谬。

嚴(yán)的 Unicode 是4E25(100111000100101),根據(jù)上表斑司,可以發(fā)現(xiàn)4E25處在第三行的范圍內(nèi)(0000 0800 - 0000 FFFF),因此嚴(yán)的 UTF-8 編碼需要三個(gè)字節(jié)宿刮,即格式是1110xxxx 10xxxxxx 10xxxxxx私蕾。然后僵缺,從“嚴(yán)”的最后一個(gè)二進(jìn)制位開(kāi)始踩叭,依次從后向前填入格式中的\color{red} {×},多出的位補(bǔ)\color{blue} {0}容贝。
這樣就得到了,“嚴(yán)”的 UTF-8 編碼是
\color{black} {1110}\color{blue} {0}\color{red} {100}?\color{black} {10}\color{red} {111000}?\color{black}{10}\color{red} {100101}斤富,
轉(zhuǎn)換成十六進(jìn)制就是E4B8A5。

Unicode 與 UTF-8 之間的轉(zhuǎn)換

里面有四個(gè)選項(xiàng):ANSI满力,Unicode,Unicode big endian和UTF-8

1)ANSI是默認(rèn)的編碼方式:對(duì)于英文文件是ASCII編碼油额,對(duì)于簡(jiǎn)體中文文件是GB2312編碼(只針對(duì) Windows 簡(jiǎn)體中文版,如果是繁體中文版會(huì)采用 Big5 碼)潦嘶;
2)Unicode編碼這里指的是notepad.exe使用的 UCS-2 編碼方式:即直接用兩個(gè)字節(jié)存入字符的 Unicode 碼,這個(gè)選項(xiàng)用的 little endian 格式;
3)Unicode big endian編碼與上一個(gè)選項(xiàng)相對(duì)應(yīng):我在下一節(jié)會(huì)解釋 little endian和 big endian 的涵義校摩;
4)UTF-8編碼:也就是上一節(jié)談到的編碼方法。

選擇完"編碼方式"后衙吩,點(diǎn)擊"保存"按鈕,文件的編碼方式就立刻轉(zhuǎn)換好了坤塞。

Little endian 和 Big endian

上一節(jié)已經(jīng)提到,UCS-2 格式可以存儲(chǔ) Unicode 碼(碼點(diǎn)不超過(guò)0xFFFF)摹芙。以漢字嚴(yán)為例,Unicode 碼是4E25浮禾,需要用兩個(gè)字節(jié)存儲(chǔ),一個(gè)字節(jié)是4E盈电,另一個(gè)字節(jié)是25。存儲(chǔ)的時(shí)候匆帚,4E在前,25在后吸重,這就是 Big endian 方式;25在前嚎幸,4E在后,這是 Little endian 方式嫉晶。

這兩個(gè)古怪的名稱來(lái)自英國(guó)作家斯威夫特的《格列佛游記》。在該書中,小人國(guó)里爆發(fā)了內(nèi)戰(zhàn)封断,戰(zhàn)爭(zhēng)起因是人們爭(zhēng)論,吃雞蛋時(shí)究竟是從大頭(Big-endian)敲開(kāi)還是從小頭(Little-endian)敲開(kāi)坡疼。為了這件事情,前后爆發(fā)了六次戰(zhàn)爭(zhēng),一個(gè)皇帝送了命闸氮,另一個(gè)皇帝丟了王位。

第一個(gè)字節(jié)在前蒲跨,就是"大頭方式"(Big endian),第二個(gè)字節(jié)在前就是"小頭方式"(Little endian)或悲。

那么很自然的,就會(huì)出現(xiàn)一個(gè)問(wèn)題:計(jì)算機(jī)怎么知道某一個(gè)文件到底采用哪一種方式編碼巡语?

Unicode 規(guī)范定義,每一個(gè)文件的最前面分別加入一個(gè)表示編碼順序的字符男公,這個(gè)字符的名字叫做"零寬度非換行空格"(zero width no-break space),用FEFF表示枢赔。這正好是兩個(gè)字節(jié),而且FF比FE大1糠爬。

如果一個(gè)文本文件的頭兩個(gè)字節(jié)是FE FF,就表示該文件采用大頭方式执隧;如果頭兩個(gè)字節(jié)是FF FE,就表示該文件采用小頭方式镀琉。

10、實(shí)例講解
下面屋摔,舉一個(gè)實(shí)例。

打開(kāi)"記事本"程序notepad.exe钓试,新建一個(gè)文本文件,內(nèi)容就是一個(gè)“嚴(yán)”字弓熏,依次采用ANSI,Unicode挽鞠,Unicode big endian和UTF-8編碼方式保存狈孔。

1)ANSI:文件的編碼就是兩個(gè)字節(jié)D1 CF材义,這正是嚴(yán)的 GB2312 編碼均抽,這也暗示 GB2312 是采用大頭方式存儲(chǔ)的其掂。
2)Unicode:編碼是四個(gè)字節(jié)FF FE 25 4E,其中FF FE表明是小頭方式存儲(chǔ)清寇,真正的編碼是4E25。
3)Unicode big endian:編碼是四個(gè)字節(jié)FE FF 4E 25华烟,其中FE FF表明是大頭方式存儲(chǔ)。
4)UTF-8:編碼是六個(gè)字節(jié)EF BB BF E4 B8 A5盔夜,前三個(gè)字節(jié)EF BB BF表示這是UTF-8編碼,后三個(gè)E4B8A5就是嚴(yán)的具體編碼喂链,它的存儲(chǔ)順序與編碼順序是一致的。

總結(jié):

簡(jiǎn)單來(lái)說(shuō):Unicode椭微、GBK和Big5碼等就是編碼的值(也就是術(shù)語(yǔ)“字符集”),而UTF-8蝇率、UTF-16、UTF32之類就是這個(gè)值的表現(xiàn)形式(即術(shù)語(yǔ)“編碼格式”)本慕。

另外:Unicode、GBK和Big5碼等字符集是不兼容的锅尘,同一個(gè)漢字在這三個(gè)字符集里的碼值是完全不一樣的。如"漢"的Unicode值與GBK就是不一樣的藤违,假設(shè)Unicode為a040,GBK為b030顿乒。以UTF-8為例,UTF-8碼完全只針對(duì)Unicode來(lái)組織的淆游,如果GBK要轉(zhuǎn)UTF-8必須先轉(zhuǎn)Unicode碼,再轉(zhuǎn)UTF-8就OK了犹菱。

即GBK、GB2312等與UTF8之間都必須通過(guò)Unicode編碼才能相互轉(zhuǎn)換:

1)GBK腊脱、GB2312 --先轉(zhuǎn)--> Unicode --再轉(zhuǎn)--> UTF8

2)UTF8 --先轉(zhuǎn)--> Unicode --再轉(zhuǎn)--> GBK、GB2312


參考文獻(xiàn):
Unicode,UTF-8,ASCII等字符編碼
字符編碼那點(diǎn)事:快速理解ASCII陕凹、Unicode、GBK和UTF-8

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末搜骡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子记靡,更是在濱河造成了極大的恐慌,老刑警劉巖摸吠,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嚎花,死亡現(xiàn)場(chǎng)離奇詭異寸痢,居然都是意外死亡紊选,警方通過(guò)查閱死者的電腦和手機(jī)啼止,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)族壳,“玉大人,你說(shuō)我怎么就攤上這事仿荆。” “怎么了拢操?”我有些...
    開(kāi)封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵舶替,是天一觀的道長(zhǎng)令境。 經(jīng)常有香客問(wèn)我顾瞪,道長(zhǎng)抛蚁,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任瞧甩,我火速辦了婚禮,結(jié)果婚禮上肚逸,老公的妹妹穿的比我還像新娘。我一直安慰自己朦促,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布务冕。 她就那樣靜靜地躺著幻赚,像睡著了一般洒疚。 火紅的嫁衣襯著肌膚如雪坯屿。 梳的紋絲不亂的頭發(fā)上油湖,一...
    開(kāi)封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天领跛,我揣著相機(jī)與錄音,去河邊找鬼吠昭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛矢棚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蒲肋,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼兜粘!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起孔轴,我...
    開(kāi)封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贷洲,沒(méi)想到半個(gè)月后收厨,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體优构,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帽氓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年俩块,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浓领。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡联贩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泪幌,到底是詐尸還是另有隱情,我是刑警寧澤祸泪,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站没隘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏右蒲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一瑰妄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧间坐,春花似錦、人聲如沸竹宋。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至宪潮,卻和暖如春趣苏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梯轻。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彬伦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓单绑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親搂橙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容