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