寫代碼的時(shí)候經(jīng)常遇到編碼問題,到底什么是編碼問題呢,?什么是編碼,?什么是字符集?他們之間有什么關(guān)系,?(某手機(jī)軟件開發(fā)公司的面試問題) 本文介紹了編碼字符集的概念以及Java與編碼字符集之間的關(guān)系,。 1. 字符 字符是抽象的最小文本單位。它沒有固定的形狀(可能是一個(gè)字形),,而且沒有值,。“A”是一個(gè)字符,,“ ”(德國(guó),、法國(guó)和許多其他歐洲國(guó)家通用貨幣的標(biāo)志)也是一個(gè)字符?!爸小薄皣?guó)”這是兩個(gè)漢字字符,。字符僅僅代表一個(gè)符號(hào),沒有任何實(shí)際值的意義,。 2. 字符集 字符集是字符的集合,。例如,漢字字符是中國(guó)人最先發(fā)明的字符,,在中文,、日文、韓文和越南文的書寫中使用,。這也說明了字符和字符集之間的關(guān)系,,字符組成字符集,。 3. 編碼字符集 編碼字符集是一個(gè)字符集(有時(shí)候也被簡(jiǎn)稱位字符集),它為每一個(gè)字符分配一個(gè)唯一數(shù)字,。最早的編碼是iso8859-1,和ascii編碼相似,。但為了方便表示各種各樣的語(yǔ)言,,逐漸出現(xiàn)了很多標(biāo)準(zhǔn)編碼。 iso8859-1:屬于單字節(jié)編碼字符集,,最多能表示的字符范圍是0-255,,應(yīng)用于英文系列,除了iso8859-1以外還有其他iso8859系列的編碼,,這些編碼都是為了滿足歐洲國(guó)家語(yǔ)言字符的需要而設(shè)計(jì)的,。
GB2312/GBK/ GB18030:前面提到的iso8859-1最多只能表示256個(gè)字符,這對(duì)于漢字來(lái)說實(shí)在是有些抱歉,,所以就有了現(xiàn)在要介紹的漢字國(guó)標(biāo)碼,,專門用來(lái)表示漢字,是雙字節(jié)編碼字符集,,而英文字母和iso8859-1一致(兼容iso8859-1編碼),。其中GBK編碼能夠用來(lái)同時(shí)表示繁體字和簡(jiǎn)體字,而GB2312只能表示簡(jiǎn)體字,,GBK是兼容GB2312編碼的,。而GB18030-2000則是一個(gè)更復(fù)雜的字符集,采用變長(zhǎng)字節(jié)的編碼方式,,能夠支持更多的字符,。需要注意的是中國(guó)政府要求所有在中國(guó)出售的軟件必須支持GB18030。
Unicode:這是最統(tǒng)一的編碼字符集,,可以用來(lái)表示所有語(yǔ)言的字符,,不兼容任何前面提到的編碼字符集。Unicode 標(biāo)準(zhǔn)始終使用十六進(jìn)制數(shù)字,,而且在書寫時(shí)在前面加上前綴“U+”,,所以“A”的編碼書寫為“U+ 0041”。注意:在JAVA語(yǔ)言中書寫時(shí)應(yīng)該使用轉(zhuǎn)義符‘\u’表示,,如 char charA = ‘\u0041’; 這種表示方法等與 char charA = ‘A’; ,。
從ASCII(英文) ==> 西歐文字 ==> 東歐字符集(俄文,希臘語(yǔ)等) ==> 東亞字符集(GB2312 BIG5 SJIS等)==> 擴(kuò)展字符集GBK GB18030這個(gè)發(fā)展過程基本上也反映了字符集標(biāo)準(zhǔn)的發(fā)展過程,,但這么隨著時(shí)間的推移,,尤其是互聯(lián)網(wǎng)讓跨語(yǔ)言的信息的交互變得越來(lái)越多的時(shí)候,太多多針對(duì)本地語(yǔ)言的編碼標(biāo)準(zhǔn)的出現(xiàn)導(dǎo)致一個(gè)應(yīng)用程序的國(guó)際化變得成本非常高,。尤其是你要編寫一個(gè)同時(shí)包含法文和簡(jiǎn)體中文的文檔,,這時(shí)候一般都會(huì)想到要是用一個(gè)通用的字符集能夠顯示所有語(yǔ)言的所有文字就好了,,而且這樣做應(yīng)用也能夠比較方便的國(guó)際化,為了達(dá)到這個(gè)目標(biāo),,即使應(yīng)用犧牲一些空間和程序效率也是非常值得的,。UNICODE就是這樣一個(gè)通用的解決方案。
4. Unicode編碼字符集
Unicode 因?yàn)楸仨殞⒅?、韓,、日、英,、法,、阿拉伯……等許多國(guó)家所使用的文字都納入,目前已經(jīng)包含了六萬(wàn)多個(gè)字符,,所以 Unicode 使用了16個(gè)位來(lái)為字符編碼,。因?yàn)?Unicode 使用了 16 位編碼,所以每個(gè)字符都用 16 位來(lái)儲(chǔ)存或傳輸是很自然的事,,這種儲(chǔ)存或傳輸?shù)母袷椒Q為UTF-16(一種Unicode的字符編碼方案,,在這里所說的UTF-16并不涉及增補(bǔ)字符的表示,本文將會(huì)在稍后介紹),。但是如果你使用到的字符都是西方字符,,那么你一定不會(huì)想用 UTF-16 的格式,因?yàn)轶w積比8位的iso8859-1多了一倍,,如此一來(lái)就必須考慮程序運(yùn)行時(shí)各種字符在內(nèi)存中所占空間的性能問題,,這便引入了字符編碼方案的概念: 字符編碼方案是從一個(gè)或多個(gè)編碼字符集到一個(gè)或多個(gè)固定寬度代碼單元序列的映射。 最常用的代碼單元是字節(jié),,所以可以簡(jiǎn)單的認(rèn)為字符編碼方案是為了告訴計(jì)算機(jī)如何將編碼字符集(如Unicode)映射到計(jì)算機(jī)可以識(shí)別的數(shù)據(jù)格式中,,如字節(jié)。這種編碼方案往往能夠?yàn)樗鶎?duì)應(yīng)的字符集在計(jì)算機(jī)處理時(shí)提供更為優(yōu)化的空間以及性能上的解決方案,。Unicode編碼字符集有三種字符編碼方案,,下面將逐一介紹: l UTF-32* 即將每一個(gè)Unicode編碼表示為相同值的32位整數(shù)。很明顯,,它是內(nèi)部處理最方便的表達(dá)方式,,但是,如果作為一般字符串表達(dá)方式,,則要消耗更多的內(nèi)存,。顯而易見,對(duì)于英文字母的表示將需要多個(gè)0字節(jié),,僅僅因?yàn)槲覀冃枰?個(gè)字節(jié)32位來(lái)表示一個(gè)Unicode字符,。
l UTF-16 使用一個(gè)或兩個(gè)未分配的 16位代碼單元的序列對(duì)Unicode編碼進(jìn)行編碼。值U+0000至U+FFFF 編碼為一個(gè)相同值的16位單元,。增補(bǔ)字符*編碼為兩個(gè)代碼單元,,第一個(gè)單元來(lái)自于高代理范圍(U+D800 至 U+DBFF),,第二個(gè)單元來(lái)自于低代理范圍(U+DC00 至U+DFFF)。這在概念上可能看起來(lái)類似于多字節(jié)編碼,,但是其中有一個(gè)重要區(qū)別:值 U+D800 至 U+DFFF 保留用于 UTF-16,;沒有這些值分配字符作為代碼點(diǎn)。這意味著,,對(duì)于一個(gè)字符串中的每個(gè)單獨(dú)的代碼單元,,軟件可以識(shí)別是否該代碼單元表示某個(gè)單單元字符,或者是否該代碼單元是某個(gè)雙單元字符的第一個(gè)或第二單元,。這相當(dāng)于某些傳統(tǒng)的多字節(jié)字符編碼來(lái)說是一個(gè)顯著的改進(jìn),,在傳統(tǒng)的多字節(jié)字符編碼中,,字節(jié)值0x41 既可能表示字母“A”,,也可能是一個(gè)雙字節(jié)字符的第二個(gè)字節(jié)。
l UTF-8 使用一至四個(gè)字節(jié)的序列對(duì)編碼Unicode進(jìn)行編碼,。U+0000至U+007F使用一個(gè)字節(jié)編碼,,U+0080至U+07FF 使用兩個(gè)字節(jié),U+0800 至U+FFFF使用三個(gè)字節(jié),,而U+10000至U+10FFFF使用四個(gè)字節(jié),。UTF-8設(shè)計(jì)原理為:字節(jié)值0x00至0x7F始終表示代碼點(diǎn)U+0000至U+007F(Basic Latin 字符子集,它對(duì)應(yīng) ASCII 字符集),。這些字節(jié)值永遠(yuǎn)不會(huì)表示其他Unicode編碼字符,,這一特性使 UTF-8 可以很方便地在軟件中將特殊的含義賦予某些 ASCII 字符。UTF-8 的格式在編碼英文時(shí),,只需要8位,,但是中文則是24位,其他更加偏僻的字符才又可能是32位,,這也是UTF-8最大的編碼特點(diǎn),,可以最高效率的利用計(jì)算機(jī)空間,因?yàn)樵谟?jì)算機(jī)處理的時(shí)候大多數(shù)情況下還是只使用英文進(jìn)行運(yùn)算和處理,,這也是為什么還需要UTF-8的主要原因,,因?yàn)楫吘够ヂ?lián)網(wǎng)70%以上的信息仍然是英文。如果連英文都用2個(gè)字節(jié)存取(UCS-2),,空間浪費(fèi)不就太多了,?
* UTF--32 表示Unicode Transformation Form 32-bit form,UTF-16,,UTF-8依此類推,。
* Unicode 最初設(shè)計(jì)是作為一種固定寬度的 16 位字符編碼。在 Java 編程語(yǔ)言中,,基本數(shù)據(jù)類型 char 初衷是通過提供一種簡(jiǎn)單的,、能夠包含任何字符的數(shù)據(jù)類型來(lái)充分利用這種設(shè)計(jì)的優(yōu)點(diǎn),。不過,現(xiàn)在看來(lái),,16 位編碼的所有65,536個(gè)字符并不能完全表示全世界所有正在使用或曾經(jīng)使用的字符,。于是,Unicode 標(biāo)準(zhǔn)已擴(kuò)展到包含多達(dá) 1,112,064個(gè)字符,。那些超出原來(lái)的16位限制的字符被稱作增補(bǔ)字符
|