計(jì)算機(jī)中的字是如何處理的?

??? 如果你用放大鏡看一下,可以看出屏幕上的字是由一個(gè)一個(gè)的像素點(diǎn)組成的,每一個(gè)字符用一組像素點(diǎn)拼接出來(lái),這些像素點(diǎn)組成一幅圖像,變成了我們的文字,計(jì)算機(jī)又是如何將我們的文字保存起來(lái)的呢?是用一個(gè)個(gè)的點(diǎn)組成的圖像將文字保存起來(lái)的嗎?當(dāng)然不是,讓我們從英文開(kāi)始,由于英文是拼音文字,實(shí)際上所有的英文字符和符號(hào)加起來(lái)也不超過(guò) 100 個(gè),在我們的文字中存在著如此大量的重復(fù)符號(hào),這就意味著保存每個(gè)字符的圖像會(huì)有大量的重復(fù),比如 e 就是出現(xiàn)最多的符號(hào)等等。所以在計(jì)算機(jī)中,實(shí)際上不會(huì)保存字符的圖像。

什么是字符編碼?

??? 由于我們的文字中存在著大量的重復(fù)字符,而計(jì)算機(jī)天生就是用來(lái)處理數(shù)字的 , 為了減少我們需要保存的信息量,我們可以使用一個(gè)數(shù)字編碼來(lái)表示每一個(gè)字符,通過(guò)對(duì)每一個(gè)字符規(guī)定一個(gè)唯一的數(shù)字代號(hào),然后,對(duì)應(yīng)每一個(gè)代號(hào),建立其相對(duì)應(yīng)的圖形,這樣,在每一個(gè)文件中,我們只需要保存每一個(gè)字符的編碼就相當(dāng)于保存了文字,在需要顯示出來(lái)的時(shí)候,先取得保存起來(lái)的編碼,然后通過(guò)編碼表,我們可以查到字符對(duì)應(yīng)的圖形,然后將這個(gè)圖形顯示出來(lái),這樣我們就可以看到文字了,這些用來(lái)規(guī)定每一個(gè)字符所使用的代碼的表格,就稱為編碼表。編碼就是對(duì)我們?nèi)粘J褂米址囊环N數(shù)字編號(hào)。

第一個(gè)編碼表 ASCII

在最初的時(shí)候,美國(guó)人制定了第一張編碼表《美國(guó)標(biāo)準(zhǔn)信息交換碼》,簡(jiǎn)稱 ASCII ,它總共規(guī)定了 128 個(gè)符號(hào)所對(duì)應(yīng)的數(shù)字代號(hào),使用了 7 位二進(jìn)制的位來(lái)表示這些數(shù)字。其中包含了英文的大小寫(xiě)字母、數(shù)字、標(biāo)點(diǎn)符號(hào)等常用的字符,數(shù)字代號(hào)從 0 127 ASCII 的表示內(nèi)容如下:

0 – 31????????????? 控制符號(hào)

32???????????????????????????????? 空格

33-47?????????????????????????? 常用符號(hào)

48-57?????????????????????????? 數(shù)字

58-64?????????????????????????? 符號(hào)

65-90?????????????????????????? 大寫(xiě)字母

91-96?????????????????????????? 符號(hào)

97-127??????????????????????? 小寫(xiě)字母

? 注意, 32 表示空格,雖然我們?cè)偌埳蠈?xiě)字時(shí),只要手腕動(dòng)一下,就可以流出一個(gè)空格,但是,在計(jì)算機(jī)上,空格與普通得字符一樣也需要用一個(gè)編碼來(lái)表示, 33-127 95 個(gè)編碼用來(lái)表示符號(hào),數(shù)字和英文的大寫(xiě)和小寫(xiě)字母。比如數(shù)字 1 所對(duì)應(yīng)的數(shù)字代號(hào)為 49 ,大寫(xiě)字母 A 對(duì)應(yīng)的代號(hào)為 65, 小寫(xiě)字母 a 對(duì)應(yīng)的代號(hào)為 97 。所以,我們所寫(xiě)的代碼 hello, world 保存在文件中時(shí),實(shí)際上是保存了一組數(shù)字 104 101 108 108 111 44 32 119 111 114 108 100 。我們?cè)俪绦蛑斜容^英文字符串的大小時(shí),實(shí)際上也是比較字符對(duì)應(yīng)的 ASCII 的編碼大小。

??? 由于 ASCII 出現(xiàn)最早,因此各種編碼實(shí)際上都受到了它的影響,并盡量與其相兼容。

? 擴(kuò)展 ASCII 編碼 ISO8859

???? 美國(guó)人順利解決了字符的問(wèn)題,可是歐洲的各個(gè)國(guó)家還沒(méi)有,比如法語(yǔ)中就有許多英語(yǔ)中沒(méi)有的字符,因此 ASCII 不能幫助歐洲人解決編碼問(wèn)題。

為了解決這個(gè)問(wèn)題,人們借鑒 ASCII 的設(shè)計(jì)思想,創(chuàng)造了許多使用 8 位二進(jìn)制數(shù)來(lái)表示字符的擴(kuò)充字符集,這樣我們就可以使用 256 種數(shù)字代號(hào)了,表示更多的字符了。在這些字符集中,從 0 - 127 的代碼與 ASCII 保持兼容,從 128 255 用于其它的字符和符號(hào),由于有很多的語(yǔ)言,有著各自不同的字符,于是人們?yōu)椴煌恼Z(yǔ)言制定了大量不同的編碼表,在這些碼表中,從 128 - 255 表示各自不同的字符,其中,國(guó)際標(biāo)準(zhǔn)化組織的 ISO8859 標(biāo)準(zhǔn)得到了廣泛的使用。

ISO8859 的編碼表中,編號(hào) 0 – 127 ASCII 保持兼容,編號(hào) 128 – 159 32 個(gè)編碼保留給擴(kuò)充定義的 32 個(gè)擴(kuò)充控制碼, 160 為空格, 161 -255 95 個(gè)數(shù)字用于新增加的字符代碼。編碼的布局與 ASCII 的設(shè)計(jì)思想如出一轍,由于在一張碼表中只能增加 95 種字符的代碼,所以 ISO8859 實(shí)際上不是一張碼表,而是一系列標(biāo)準(zhǔn),包括 14 個(gè)字符碼表。例如,西歐的常用字符就包含在 ISO8859-1 字符表中。在 ISO8859-7 種則包含了 ASCII 和現(xiàn)代希臘語(yǔ)字符。

?

問(wèn)題出現(xiàn)了!

?

??? ISO 8859 標(biāo)準(zhǔn)解決了大量的字符編碼問(wèn)題,但也帶來(lái)了新的問(wèn)題,比如說(shuō),沒(méi)有辦法在一篇文章中同時(shí)使用 ISO8859-1 ISO8859-7 ,也就是說(shuō),在同一篇文章中不能同時(shí)出現(xiàn)希臘文和法文,因?yàn)樗麄兊木幋a范圍是重合的。例如:在 ISO8859-1 217 號(hào)編碼表示字符 ù ,而在 ISO8859-7 中則表示希臘字符 Ω ,這樣一篇使用 ISO8859-1 保存的文件,在使用 ISO8859-7 編碼的計(jì)算機(jī)上打開(kāi)時(shí),將看到錯(cuò)誤的內(nèi)容。為了同時(shí)處理一種以上的文字,甚至還出現(xiàn)了一些同時(shí)包含原來(lái)不屬于同一張碼表的字符的新碼表。

?

大字符集的煩惱

??? 不管如何,歐洲的拼音文字都還可以用一個(gè)字節(jié)來(lái)保存,一個(gè)字節(jié)由 8 個(gè)二進(jìn)制的位組成,用來(lái)表示無(wú)符號(hào)的整數(shù)的話,范圍正好是 0 – 255

但是,更嚴(yán)重的問(wèn)題出現(xiàn)在東方,中國(guó),朝鮮和日本的文字包含大量的符號(hào)。例如,中國(guó)的文字不是拼音文字,漢字的個(gè)數(shù)有數(shù)萬(wàn)之多,遠(yuǎn)遠(yuǎn)超過(guò)區(qū)區(qū) 256 個(gè)字符,因此 ISO 8859 標(biāo)準(zhǔn)實(shí)際上不能處理中文的字符。

通過(guò)借鑒 ISO8859 的編碼思想,中國(guó)的專家靈巧的解決了中文的編碼問(wèn)題。

既然一個(gè)字節(jié)的 256 種字符不能表示中文,那么,我們就使用兩個(gè)字節(jié)來(lái)表示一個(gè)中文,在每個(gè)字符的 256 種可能中,低于 128 的為了與 ASCII 保持兼容,我們不使用,借鑒 ISO8859 的設(shè)計(jì)方案,只使用從 160 以后的 96 個(gè)數(shù)字,兩個(gè)字節(jié)分成高位和低位,高位的取值范圍從 176-247 72 個(gè),低位從 161 – 254 94 這樣,兩個(gè)字節(jié)就有 72 * 94 = 6768 種可能,也就是可以表示 6768 種漢字,這個(gè)標(biāo)準(zhǔn)我們稱為 GB2312-80

6768 個(gè)漢字顯然不能表示全部的漢字,但是這個(gè)標(biāo)準(zhǔn)是在 1980 年制定的,那時(shí)候,計(jì)算機(jī)的處理能力,存儲(chǔ)能力都還很有限,所以在制定這個(gè)標(biāo)準(zhǔn)的時(shí)候,實(shí)際上只包含了常用的漢字,這些漢字是通過(guò)對(duì)日常生活中的報(bào)紙,電視,電影等使用的漢字進(jìn)行統(tǒng)計(jì)得出的,大概占常用漢字的 99% 。因此,我們時(shí)常會(huì)碰到一些名字中的特殊漢字無(wú)法輸入到計(jì)算機(jī)中的問(wèn)題,就是由于這些生僻的漢字不在 GB2312 的常用漢字之中的緣故。

由于 GB2312 規(guī)定的字符編碼實(shí)際上與 ISO8859 是沖突的,所以,當(dāng)我們?cè)谥形沫h(huán)境下看一些西文的文章,使用一些西文的軟件的時(shí)候,時(shí)常就會(huì)發(fā)現(xiàn)許多古怪的漢字出現(xiàn)在屏幕上,實(shí)際上就是因?yàn)槲魑闹惺褂昧伺c漢字編碼沖突的字符,被我們的系統(tǒng)生硬的翻譯成中文造成的。

不過(guò), GB2312 統(tǒng)一了中文字符編碼的使用,我們現(xiàn)在所使用的各種電子產(chǎn)品實(shí)際上都是基于 GB2312 來(lái)處理中文的。

GB2312-80 僅收漢字 6763 個(gè),這大大少于現(xiàn)有漢字,隨著時(shí)間推移及漢字文化的不斷延伸推廣,有些原來(lái)很少用的字,現(xiàn)在變成了常用字,例如:朱镕基的 字,未收入 GB2312-80 ,現(xiàn)在大陸的報(bào)業(yè)出刊只得使用(金 + 容)、(金容)、(左金右容)等來(lái)表示,形式不一而同,這使得表示、存儲(chǔ)、輸入、處理都非常不方便,而且這種表示沒(méi)有統(tǒng)一標(biāo)準(zhǔn)。

為了解決這些問(wèn)題,全國(guó)信息技術(shù)化技術(shù)委員會(huì)于 1995 12 1 《漢字內(nèi)碼擴(kuò)展規(guī)范》。 GBK 向下與 GB2312 完全兼容,向上支持 ISO 10646 國(guó)際標(biāo)準(zhǔn),在前者向后者過(guò)渡過(guò)程中起到的承上啟下的作用。 GBK 亦采用雙字節(jié)表示,總體編碼范圍為 8140-FEFE 之間,高字節(jié)在 81-FE 之間,低字節(jié)在 40-FE 之間,不包括 7F 。在 GBK 1.0 中共收錄了 21886 個(gè)符號(hào),漢字有 21003 個(gè)。

GBK 共收入 21886 個(gè)漢字和圖形符號(hào),包括:

* GB2312 中的全部漢字、非漢字符號(hào)。

* BIG5 中的全部漢字。

* ISO 10646 相應(yīng)的國(guó)家標(biāo)準(zhǔn) GB13000 中的其它 CJK 漢字,以上合計(jì) 20902 個(gè)漢字。

* 其它漢字、部首、符號(hào),共計(jì) 984 個(gè)。

?

微軟公司自 Windows 95 簡(jiǎn)體中文版開(kāi)始支持 GBK 代碼,但目前的許多軟件都不能很好地支持 GBK 漢字。

GBK 編碼區(qū)分三部分:

* 漢字區(qū) 包括

GBK/2 OXBOA1-F7FE, 收錄 GB2312 漢字 6763 個(gè),按原序排列;

GBK/3 OX8140-AOFE ,收錄 CJK 漢字 6080 個(gè);

GBK/4 OXAA40-FEAO ,收錄 CJK 漢字和增補(bǔ)的漢字 8160 個(gè)。

* 圖形符號(hào)區(qū) 包括

GBK/1 OXA1A1-A9FE ,除 GB2312 的符號(hào)外,還增補(bǔ)了其它符號(hào)

GBK/5 OXA840-A9AO ,擴(kuò)除非漢字區(qū)。

* 用戶自定義區(qū)

GBK 區(qū)域中的空白區(qū),用戶可以自己定義字符。

?GB18030 是最新的漢字編碼字符集國(guó)家標(biāo)準(zhǔn) , 向下兼容 GBK GB2312 標(biāo)準(zhǔn)。 GB18030 編碼是一二四字節(jié)變長(zhǎng)編碼。一字節(jié)部分從 0x0~0x7F ASCII 編碼兼容。二字節(jié)部分 , 首字節(jié)從 0x81~0xFE, 尾字節(jié)從 0x40~0x7E 以及 0x80~0xFE, GBK 標(biāo)準(zhǔn)基本兼容。四字節(jié)部分 , 第一字節(jié)從 0x81~0xFE, 第二字節(jié)從 0x30~0x39, 第三和第四字節(jié)的范圍和前兩個(gè)字節(jié)分別相同。

? 不一樣的中文

? 中文的問(wèn)題好像也解決了,且慢,新的問(wèn)題又來(lái)了。

中國(guó)的臺(tái)灣省也在使用中文,但是由于歷史的原因,那里沒(méi)有使用大陸的簡(jiǎn)體中文,還在使用著繁體的中文,并且他們自己也制定了一套表示繁體中文的字符編碼,稱為 BIG5, 不幸的是,雖然他們的也使用兩個(gè)字節(jié)來(lái)表示一個(gè)漢字,但他們沒(méi)有象我們兼容 ASCII 一樣兼容大陸的簡(jiǎn)體中文,他們使用了大致相同的編碼范圍來(lái)表示繁體的漢字。天哪 ! ISO8859 的悲劇又出現(xiàn)在同樣使用漢字的中國(guó)人身上了,同樣的編碼在大陸和臺(tái)灣的編碼中實(shí)際上表示不同的字符,大陸的玩家在玩臺(tái)灣的游戲時(shí),經(jīng)常會(huì)遇到亂碼的問(wèn)題,問(wèn)題根源就在于,大陸的計(jì)算機(jī)默認(rèn)字符的編碼就是 GB2312, 當(dāng)碰到臺(tái)灣使用 BIG5 編碼的文字時(shí),就會(huì)作出錯(cuò)誤的轉(zhuǎn)換。

? 由于歷史和文化的原因,日文和韓文中也包含許多的漢字,象漢字一樣擁有大量的字符,不幸的是,他們的字符編碼也同樣與中文編碼有著沖突,日文的游戲在大陸上一樣也會(huì)出現(xiàn)無(wú)法理解的亂碼。《中文之星》,《南極星》,《四通利方》就是用于在這些編碼中進(jìn)行識(shí)別和轉(zhuǎn)換的專用軟件。

? 互聯(lián)的時(shí)代

? 在二十世紀(jì)八十年代后期,互聯(lián)網(wǎng)出現(xiàn)了,一夜之間,地球村上的人們可以直接訪問(wèn)遠(yuǎn)在天邊的服務(wù)器,電子文件在全世界傳播,在一切都在數(shù)字化的今天,文件中的數(shù)字到底代表什么字?這可真是一個(gè)問(wèn)題。

?UNICODE

? 實(shí)際上問(wèn)題的根源在于我們有太多的編碼表。

? 如果整個(gè)地球村都使用一張統(tǒng)一的編碼表,那么每一個(gè)編碼就會(huì)有一個(gè)確定的含義,就不會(huì)有亂碼的問(wèn)題出現(xiàn)了。

實(shí)際上,在 80 年代就有了一個(gè)稱為 UNICODE 的組織,這個(gè)組織制定了一個(gè)能夠覆蓋幾乎任何語(yǔ)言的編碼表,在 Unicode3.0.1 中就包含了 49194 個(gè)字符,將來(lái), Unicode 中還會(huì)增加更多的字符。 Unicode 的全稱是 Universal Multiple-Octet Coded Character Set ,簡(jiǎn)稱為 UCS

由于要表示的字符如此之多,所以一開(kāi)始的 Unicode1.0 編碼就使用連續(xù)的兩個(gè)字節(jié)也就是一個(gè) WORD 來(lái)表示編碼,比如 UCS 編碼就是 6C49 。這樣在 Unicode 的編碼中就可以表示 256*256 = 65536 種符號(hào)了。

直接使用一個(gè) WORD 相當(dāng)于兩個(gè)字節(jié)來(lái)保存編碼可能是最為自然的 Unicode 編碼的方式,這種方式被稱為 UCS-2 ,也被稱為 ISO 10646 ,,在這種編碼中,每一個(gè)字符使用兩個(gè)字節(jié)來(lái)進(jìn)行表示,例如, 使用 11598 來(lái)編碼,而大寫(xiě)字母 A 仍然使用 65 表示,但它占用了兩個(gè)字節(jié),高位用 0 來(lái)進(jìn)行補(bǔ)齊。

?

由于每個(gè) WORD 表示一個(gè)字符,但是在不同的計(jì)算機(jī)上,實(shí)際上對(duì) WORD 有兩種不同的處理方式,高字節(jié)在前,或者低字節(jié)在前,為了在 UCS-2 編碼的文檔中,能夠區(qū)分到底是高字節(jié)在前,還是低字節(jié)在前,使用 UCS-2 的文檔使用了一組不可能在 UCS-2 種出現(xiàn)的組合來(lái)進(jìn)行區(qū)分,通常情況下,低字節(jié)在前,高字節(jié)在后,通過(guò)在文檔的開(kāi)頭增加 FFFE 來(lái)進(jìn)行表示。高字節(jié)在前,低字節(jié)在后,稱為大頭在前,即 Big Endian ,使用 FFFE 來(lái)進(jìn)行表示。這樣,程序可以通過(guò)文檔的前兩個(gè)字節(jié),立即判斷出該文檔是否高字節(jié)在前。

Endian 這個(gè)詞出自《格列佛游記》,小人國(guó)的內(nèi)戰(zhàn)就源于吃雞蛋時(shí)要先吃大頭 big endian 還是小頭 little-endian ,并由此發(fā)生了內(nèi)戰(zhàn)。

?

理想與現(xiàn)實(shí)

?UCS-2 雖然理論上可以統(tǒng)一編碼,但仍然面臨著現(xiàn)實(shí)的困難。

首先, UCS-2 不能與現(xiàn)有的所有編碼兼容,現(xiàn)有的文檔和軟件必須針對(duì) Unicode 進(jìn)行轉(zhuǎn)換才能使用。即使是英文也面臨著單字節(jié)到雙字節(jié)的轉(zhuǎn)換問(wèn)題。

其次,許多國(guó)家和地區(qū)已經(jīng)以法律的形式規(guī)定了其所使用的編碼,更換為一種新的編碼不現(xiàn)實(shí)。比如在中國(guó)大陸,就規(guī)定 GB2312 是大陸軟件、硬件編碼的基礎(chǔ)。

第三,現(xiàn)在還有使用中的大量的軟件和硬件是基于單字節(jié)的編碼實(shí)現(xiàn)的, UCS-2 的雙字節(jié)表示的字符不能可靠的在其上工作。

?

新希望 UTF-8

? 為了盡可能與現(xiàn)有的軟件和硬件相適應(yīng),美國(guó)人又制定了一系列用于傳輸和保存 Unicode 的編碼標(biāo)準(zhǔn) UTF ,這些編碼稱為 UCS 傳輸格式碼,也就是將 UCS 的編碼通過(guò)一定的轉(zhuǎn)換,來(lái)達(dá)到使用的目的。常見(jiàn)的有 UTF-7 UTF-8 UTF-16 等。

其中 UTF-8 編碼得到了廣泛的應(yīng)用, UTF-8 的全名是 UCS Transformation Format 8, UCS 編碼的 8 位傳輸格式,就是使用單字節(jié)的方式對(duì) UCS 進(jìn)行編碼,使 Unicode 編碼能夠在單字節(jié)的設(shè)備上正常進(jìn)行處理。

UTF-8 編碼是變長(zhǎng)的編碼,對(duì)不同的 Unicode 可能編成不同的長(zhǎng)度

?

UCS-2????????????????????????????????????????????????????????????? UTF-8

0000-007F?? 0- 127???????????????????????? 0xxxxxxx

0080-07FF 128- 2047????????????????????? 110xxxxx 10xxxxxx

???????? 0800-FFFF 2048-65535???????????????????? 1110xxxx 10xxxxxx 10xxxxxx

?

???? 例如 1 Unicode 編碼是 31 00, 0-127 之間,所以轉(zhuǎn)換后即為 31 ,而 字的 UTF-8 Unicode 編碼為 11598 ,轉(zhuǎn)換成 UTF-8 則為 e4 b8 ad

?

實(shí)際上, ASCII 字符用 UTF-8 來(lái)表示后,與 ASCII 是完全一樣的,美國(guó)人又近水樓臺(tái)的把自己的問(wèn)題解決了。但其他的編碼就沒(méi)有這么幸運(yùn)了。

? 突破障礙 - Unicode 與本地編碼的轉(zhuǎn)換

UTF-8 編碼解決了字符的編碼問(wèn)題,又可以在現(xiàn)有的設(shè)備上通行,因此,得到了廣泛的使用,

????????? XML 中的問(wèn)題

???????? XML 的設(shè)計(jì)目標(biāo)是實(shí)現(xiàn)跨網(wǎng)絡(luò),跨國(guó)界的信息表示,所以,在 XML 設(shè)計(jì)之初,就規(guī)定 XML 文件的默認(rèn)編碼格式就是 UTF-8 ,也就是說(shuō),如果沒(méi)有特殊的說(shuō)明, XML 文件將被視為  UTF-8 編碼。

然而,大部分的中文編輯軟件,是根據(jù)操作系統(tǒng)來(lái)決定編碼的方式的,所以,在寫(xiě)字板中直接輸入并保存的文件,將被保存為 GB2312 編碼,所以,在讀出 XML 文件內(nèi)容時(shí),往往就會(huì)出現(xiàn)文件錯(cuò)誤的提示了。這種情況會(huì)出現(xiàn)在文件中有中文出現(xiàn)的時(shí)候,如果沒(méi)有中文,只有英文信息,就不會(huì)出現(xiàn)問(wèn)題。原因很簡(jiǎn)單,有中文時(shí),因?yàn)橹形牡木幋a并不是 UTF-8 編碼,所以會(huì)造成沖突,沒(méi)有中文時(shí),英文的編碼在 GB2312 中與 ASCII 是兼容的,而 ASCII UTF-8 是完全一致的,所以不會(huì)出現(xiàn)問(wèn)題。這種情況也包括 UltraEdit 軟件。

但時(shí),專業(yè)的 XML 編輯軟件會(huì)自動(dòng)將內(nèi)容保存為  UTF-8 編碼,不會(huì)有問(wèn)題。

在通過(guò) DOM XSLT 保存 XML 文件時(shí)也有著同樣的問(wèn)題。

默認(rèn)情況下, XML 的處理程序一般會(huì)將內(nèi)容作為 UTF-8 編碼進(jìn)行處理,所以保存下來(lái)的 XML 文件必須要用可以識(shí)別 UTF-8 的軟件來(lái)進(jìn)行查看,如 Windows 的記事本。

?

???????? Java 的處理

Java 的設(shè)計(jì)目標(biāo)是一次編寫(xiě),到處運(yùn)行,所以在  Java 的內(nèi)部對(duì)字符的處理采用了 UCS 來(lái)處理,因此 Java 的字符類(lèi)型不再是 C++ 中的一個(gè)字節(jié),而使用兩個(gè)字節(jié)來(lái)保存一個(gè)字符。

但是,我們會(huì)發(fā)現(xiàn),在 Java 的文件流中保存為文件后,我們可以直接使用記事本或 UltraEdit 打開(kāi)察看。

在這里, Java 采用了一個(gè)靈巧的默認(rèn)轉(zhuǎn)換機(jī)制,當(dāng)需要將內(nèi)容中的字符保存到文件中時(shí), Java 會(huì)自動(dòng)的查看一下系統(tǒng)的本地編碼,系統(tǒng)的本地編碼可以在控制面板中查到,然后,自動(dòng)將 UCS 編碼的字符轉(zhuǎn)換為本地編碼,并進(jìn)行保存。當(dāng)需要從系統(tǒng)的文件系統(tǒng)中讀入一個(gè)文件時(shí), Java 通過(guò)查看系統(tǒng)的本地編碼來(lái)決定如何識(shí)別文件的內(nèi)容。這樣, Java 就可以在內(nèi)部使用 UCS ,但用戶可以直接使用本地編碼的文件了。

Java 在相應(yīng)的方法中,提供了額外的參數(shù),可以讓用戶自己來(lái)指定文件的編碼。

????????? .Net 的處理

??? 在微軟的 .Net 內(nèi)部,同樣使用 UCS 編碼,但是,在對(duì)文件進(jìn)行處理的時(shí)候,與 Java 有一些區(qū)別, .Net 不查詢系統(tǒng)的本地編碼,而是直接使用磨人的 UTF-8 編碼進(jìn)行文件的處理,所以,你保存的中文內(nèi)容,在 UltraEdit 中可能就是亂碼,但是,如果你使用記事本打開(kāi)的話,就不會(huì)有問(wèn)題,因?yàn)?/font> Windows 的記事本可以識(shí)別 UTF-8 的編碼。

.Net 軟件的配置文件使用 XML 格式,默認(rèn)的編碼一樣是 UTF-8 ,所以,必須使用可以識(shí)別 UTF-8 的軟件進(jìn)行處理,如: vs.net ,記事本等。

.Net 中,網(wǎng)頁(yè)默認(rèn)處理編碼就是 UTF-8

?

???????? Web 中的問(wèn)題

網(wǎng)頁(yè)的編碼問(wèn)題主要有兩點(diǎn),一是網(wǎng)頁(yè)是如何編碼的,二是如何告訴瀏覽器如何編碼的。

第一個(gè)問(wèn)題,又可以分成靜態(tài)頁(yè)面和動(dòng)態(tài)頁(yè)面兩個(gè)問(wèn)題。

對(duì)靜態(tài)頁(yè)面,網(wǎng)頁(yè)的編碼要看你保存文件時(shí)的編碼選項(xiàng),多數(shù)的網(wǎng)頁(yè)編輯軟件可以讓你選擇編碼的類(lèi)型,默認(rèn)為本地編碼,為了使網(wǎng)頁(yè)減少編碼的問(wèn)題,最好保存為 UTF-8 編碼格式。

對(duì)動(dòng)態(tài)頁(yè)面,如 Servlet 生成的頁(yè)面,在 HttpServletResponse 類(lèi)中有一個(gè)方法 setContentType ,可以通過(guò)參數(shù)來(lái)指定生成的頁(yè)面的類(lèi)型和編碼,例如: response.setContentType("text/html; charset=utf-8"); 來(lái)指定生成的頁(yè)面的編碼類(lèi)型。

對(duì) jsp 頁(yè)面可以通過(guò) <%@ page contentType="text/html;charset=gb2312" %> 來(lái)指定生成的頁(yè)面的編碼及類(lèi)型。

第二個(gè)問(wèn)題,如何通知瀏覽器網(wǎng)頁(yè)的編碼類(lèi)型。

瀏覽器收到只是一個(gè)字節(jié)流,它并不知道頁(yè)面是如何編碼的,因此,需要一個(gè)機(jī)制來(lái)告訴瀏覽器頁(yè)面的編碼類(lèi)型,標(biāo)準(zhǔn)的機(jī)制是使用 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 來(lái)指定頁(yè)面的編碼,當(dāng)瀏覽器讀取頁(yè)面遇到這樣的指示時(shí),將使用這里制定的編碼方式重新加載頁(yè)面。

否則的話,瀏覽器將會(huì)試圖猜出頁(yè)面的編碼類(lèi)型。

?

???????? Tomcat 中的中文問(wèn)題

? Tomcat 中,經(jīng)常遇到取回客戶端提交的信息是亂碼的問(wèn)題。

當(dāng)提交表單的時(shí)候, HTML 頁(yè)面的 Form 標(biāo)簽會(huì)使情況變得更為復(fù)雜。瀏覽器的編碼方式取決于當(dāng)前頁(yè)面的編碼設(shè)定,對(duì) Form 標(biāo)簽也照此處理。這意味著如果 ASCII 格式的 HTML 頁(yè)面用 ISO-8859-1 編碼,那么用戶在此頁(yè)面中將不能提交中文字符。所以,如果你的頁(yè)面使用的是 utf-8 ,那么 POST 的時(shí)候,也將使用 utf-8

由于 Tomcat 是美國(guó)人設(shè)計(jì)的, Tomcat 默認(rèn)使用 ISO8859-1 編碼隊(duì)客戶端返回的內(nèi)容進(jìn)行解碼,由于編碼與內(nèi)容不一致,就會(huì)出現(xiàn)亂碼的 ??? 出現(xiàn),根據(jù)以上的分析,在服務(wù)器端讀取客戶端回送的內(nèi)容時(shí),需要首先設(shè)定回送內(nèi)容的編碼,然后再進(jìn)行信息的讀取,通過(guò)使用 HttpServletRequest 的方法 setCharacterEncoding("utf-8") 先行設(shè)定信息的編碼類(lèi)型。然后,就可以正確讀取內(nèi)容了。

? 總結(jié)

? 編碼問(wèn)題是信息處理的基本問(wèn)題,但是由于歷史和政治的問(wèn)題,事實(shí)上存在著大量不統(tǒng)一的編碼方式,造成在信息處理過(guò)程中的信息丟失,轉(zhuǎn)換錯(cuò)誤等問(wèn)題, UCS 為問(wèn)題的解決提供了一個(gè)很好的方向,但是,在現(xiàn)在的軟件環(huán)境中,還沒(méi)有達(dá)到全面地使用。在實(shí)際中工作中應(yīng)盡量采用統(tǒng)一的編碼格式,減少編碼問(wèn)題的發(fā)生

?