計(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ā)生
?