今天看了子華的博客中關(guān)于昨晚我們討論編碼方面的問(wèn)題,發(fā)現(xiàn)其中有一個(gè)關(guān)鍵點(diǎn)沒(méi)有談到。
??? 情況是這樣的:我們現(xiàn)在使用的一個(gè)名為Notepad++的編輯器,它大體上和UltraEdit類(lèi)似,是我從sourceforge上下載下載使用的。它有個(gè)格式的功能,簡(jiǎn)單而言就是設(shè)置使用ascii編碼編輯文檔還是使用utf-8編碼,其實(shí)這里主要是對(duì)應(yīng)非英文方面的字符才發(fā)生差異。
??? 如前那篇隨筆所述utf-8只是用于在數(shù)據(jù)傳輸時(shí)將字符串分割成字節(jié)傳輸出去,它對(duì)于unicode編碼有著嚴(yán)格的一一對(duì)應(yīng)關(guān)系,而對(duì)于gb2312、gbk、gb18030之類(lèi)的中文編碼是沒(méi)有對(duì)應(yīng)關(guān)系的。gb2312、gbk、gb18030是在ascii編碼之上進(jìn)行的中文編碼開(kāi)發(fā),所以它們是與ascii相兼容的,可以這么理解在我們的文本編輯器中ascii方式編輯的文本是以ascii碼保存,而以u(píng)tf-8方式編輯的文本是以u(píng)nicode編碼保存。
??? 現(xiàn)在,編碼的差異就在這里發(fā)生了,unicode中的英文部分編碼是與ascii相兼容的,具體而言是iso8859-1兼容,所以我們無(wú)論用什么編碼保存方式保存jsp文件,在網(wǎng)頁(yè)上顯示的都是正確的英文字符。但是對(duì)于中文這個(gè)保存的格式卻非常重要。在了解了jsp頁(yè)面的顯示過(guò)程我們就會(huì)明白其中的原因。
??? 現(xiàn)在回頭來(lái)看看jsp文件是經(jīng)過(guò)了哪些步驟才在網(wǎng)頁(yè)上顯示出來(lái)的。
??? 1、首先我們用編輯器編輯jsp頁(yè)面代碼保存;
??? 2、web服務(wù)器對(duì)其進(jìn)行編譯,將jsp頁(yè)面編譯成為一個(gè)java的class文件;
??? 3、web服務(wù)器將其class文件用傳輸格式在網(wǎng)絡(luò)上傳輸;
??? 4、客戶端瀏覽器解析代碼生成頁(yè)面。
??? 過(guò)程大致如上,能夠影響編碼方面的基本上在1、2、4方面,所以對(duì)其進(jìn)行詳細(xì)講解。
??? 我們的編輯器是有一種默認(rèn)的編碼保存方式的。這會(huì)到后面java編譯器是否將其中的中文進(jìn)行轉(zhuǎn)換的問(wèn)題。大家都知道java是以十六位的unicode編碼編譯、存儲(chǔ)java文件的。因?yàn)橥粋€(gè)漢字在unicode編碼和gb2312編碼中的位置是不一樣的,(具體而言就是這兩種編碼沒(méi)有兼容性,也不能通過(guò)公式換算出來(lái),只能通過(guò)字符對(duì)應(yīng)表進(jìn)行轉(zhuǎn)換)
??? 上面指出的保存格式的重要性就在這里體現(xiàn)出來(lái)了,這也是很多人容易遺漏之處,當(dāng)我們用默認(rèn)格式位gbk的編輯器編輯jsp頁(yè)面,而在其頭部聲明charset=utf-8,那么返回的頁(yè)面會(huì)出現(xiàn)亂碼,而charset=gb2312則正常顯示。本人分析原因在于,在charset=utf-8的聲明有誤時(shí),java編譯器會(huì)錯(cuò)誤的認(rèn)為現(xiàn)在保存的文件就是以u(píng)nicode編碼格式保存的文件,所以在編譯中就不對(duì)其中的中文字符進(jìn)行g(shù)b2312--unicode的轉(zhuǎn)化,而直接將其gb2312指向的編碼地址保存為unicode的編碼地址。反之,當(dāng)編輯器的默認(rèn)編輯保存格式為utf-8時(shí),在jsp中聲明為gb2312,就會(huì)讓編譯器畫(huà)蛇添足的多進(jìn)行一次中文編碼轉(zhuǎn)換,從而亂碼出現(xiàn)。
??? 綜上所述,編輯器的默認(rèn)編碼方式是在解決中文亂碼方面是很重要的一個(gè)因素,當(dāng)然我們可以用pageEncoding參數(shù)來(lái)說(shuō)明文本編碼形式。弄清中文顯示后面的具體調(diào)用過(guò)程是徹底解決該類(lèi)問(wèn)題的終極之道!