=====================================
開發java應用程式出現亂碼是很常見的,畢竟現在unicode的使用還不是很廣泛,在使用gb2312(包含了gbk簡體,big5繁體)的系統中要正確實現
中文的display和資料庫的儲存是最基本的要求。
================================
1,首先developer要明確為什麼會遇到亂碼,遇到什麼樣的亂碼(無意義的符號還是一串問號或者其它什麼東西)。
新手遇到一堆很亂的字元時通常會不知所措,最直接的反映就是打開google搜尋」java中文」(這個字串在搜尋引擎上的查詢頻率非常高),
然後一個一個的去看別人的解決方法。這樣做沒有錯,但是很難達到目的,原因下面會提到。
總之,出現亂碼的原因是非常多的,解決的方法也完全不一樣,要解決問題必須先分析自己的」上下文環境」。
==============================
2,具體說來,需要哪些資訊才能確定專案中的亂碼的根源。
a,開發者所用的作業系統
b,j2ee容器的名稱,版本
c,資料庫的名稱,版本(精確版本)以及jdbc驅動的版本
d,出現亂碼的source code(例如是system out 出來的,還是jsp頁面中的,如果是jsp中的,那麼頭部聲明的情況也很重要)
=============== ==============================================
3,如何初步分析亂碼出現的原因。
有了上述的訊息,基本上就可以發文求助了,相信放到javaworld等論壇上,很快就會有高手給你提出有效的解決方案的。
當然不能總靠發文求助,也要試試自行解決問題。如何下手呢?
a,分析一下你的」亂碼」到底是什麼編碼。這個其實不難,例如
System.out.println(testString);
這一段出現了亂碼,那麼不妨用窮舉法猜測一下它的實際編碼格式。
System.out.println(new String(testString.getBytes(”ISO-8859-1″),”gb2312″));
System.out.println(new String(testString.getBytes(”UTF8″),”gb2312″));
System.out.println(new String(testString.getBytes(”GB2312″),”gb2312″));
System.out.println(new String(testString.getBytes(”GBK”),”gb2312″));
System.out.println(new String(testString.getBytes(”BIG5″),”gb2312″));
等等,上述程式碼的意思是用制定的編碼格式去讀取testString這個”亂碼”,並轉換成gb2312(此處僅以中文為例)
然後你看哪一個轉換出來的結果是ok的,那就。 。 。
b,如果用上面的步驟能得到正確的中文,表示你的數據肯定是在的,只不過是介面中沒有正確顯示而已。那麼第二步就該修正你的view部分了
,通常要檢查的是jsp中是否選擇了正確的頁面編碼。
在此要宣告被很多人誤解的一點,那就是<%@ page contentType=”text/html; charset=GB2312″ %>指令和<META http-equiv=Content-Type
content=”text/html; charset= gb2312″>兩者的差異。通常網路上的許多文章在提到中文問題時都是說資料庫中選擇unicode或gb2312存儲,
同時
在jsp中用page指令聲明編碼就可以解決。但我覺得這種說法很不負責任,害的我費了N多時間為本來並不存在的亂碼而鬱悶。實際上page
的作用是在jsp被編譯成為html的過程中提供編碼方式讓java來」讀取」表達式當中的String(有點類似於上面的第三個語句的作用),而meta
的作用是眾所周知的為IE瀏覽器提供編碼選擇,是用來」顯示」最後的資料的。但沒有看到有人提醒這一點,我一直把page當成meta在用,
導致本來是iso-8859的數據,被page指令讀成gb2312,於是亂碼,所以又加了編碼轉化的函數把所有的string數據都從iso8859轉到gb2312(
為什麼
這麼轉,當時也沒考慮這麼多,因為這麼做可以正常顯示了,所以就這麼改了,呵呵當時實在沒有時間慢慢排查問題了)。================================================== =============
4,資料庫選擇什麼樣的編碼比較好。
目前流行的DB主要有sql server,mysql,oracle,DB2等,其中mysql作為免費DB中的老大,性能和功能是得到公認的,安裝配置比較方便,
相應
的driver也比較完善,性價比是絕對的OK。所以就以mysql為例。
我個人建議採用mysql的預設編碼來存儲,也就是iso-8859-1(在mysql的選項中對應於latin-1)。理由主要有這麼幾個,一是iso-8859-1對
中文
的支援不錯;二是跟java中的預設編碼一致,至少在很多地方免除了轉換編碼的麻煩;三是預設的比較穩定,相容性也更好,因為多編碼的
支援是由具體的DB產品提供的,別說跟其它的DB會不相容,即使自身的不同版本也可能出現兼容性的問題。
例如mysql 4.0以前的產品中,很多中文的解決方案是利用connection中的characterEncoding字段來製定編碼,例如gb2312什麼的,這樣是ok的
,因為原始資料都是ISO8859_1編碼,jdbc驅動會採用url裡面指定的character set來進行編碼,resultSet.getString(*)取出的就是編碼後的
字串。這樣就直接拿到gb2312的數據了。
但是mysql 4.1的推出給許多dbadmin帶來了不小的麻煩,因為mysql4.1支援column level的character set,每個table,column都可以指定編碼
,不指定就是ISO8895_1,因此jdbc取出資料後會根據column的character set來進行編碼,而不再是用一個全域的參數來取所有的資料了。
這從另一個方面也說明了亂碼問題的產生實在是很複雜的事情,原因太多了。我也只是針對自己遇到的實際情況提供一些解決思路,有什麼
錯誤
的地方請email至[email protected] .希望能更多的看到達人自己的文章,而不是一堆以訥傳蹬的拷貝。
Internel Use Only.
Any Question,please reffer to [email protected]
================================================== ==============
終於找到最完美的解決中文問題的方案了。 。 。謝謝網路上的這個文章的作者。 。 。
我的原文是根據自己的經驗總結出來的。雖然沒什麼錯誤,但是始終沒有找到最終的病根。看了這篇文章之後,開始恍然大悟,哈哈,
—————————————————————————————————————————————————— —————————-
由於Java程式設計中的中文問題是一個老生常談的問題,在閱讀了許多關於Java中文問題解決方法之後,結合作者的程式設計實踐,我發現過去談的許多方法都不能清楚說明問題及解決問題,尤其是跨平台時的中文問題。
於是我給出此篇文章,內容包括對控制台運行的class、Servelets、JSP及EJB類中的中文問題我剖析和建議解決辦法。希望大家指教。
Abstract:本文深入分析了Java程式設計中Java編譯器對Java原始檔和JVM對class類別檔案的編碼/解碼過程,透過此過程的解析透視出了Java程式設計中中文問題產生的根本原因,最後給出了建議的最優化的解決Java中文問題的方法。
1.中文問題的來源電腦
最初的作業系統支援的編碼是單字節的字元編碼,於是,在電腦中一切處理程序最初都是以單字節編碼的英文為準進行處理。
隨著電腦的發展,為了適應世界其它民族的語言(當然包括我們的漢字),人們提出了UNICODE編碼,它採用雙字節編碼,兼容英文字符和其它民族的雙字節字符編碼,所以,目前,大多數國際性的軟體內部均採用UNICODE編碼,在軟體運行時,它獲得本地支援系統(多數時間是作業系統)預設支援的編碼格式,然後再將軟體內部的UNICODE轉換為本地系統預設支援的格式顯示出來。
Java的JDK和JVM就是如此,我在這裡說的JDK是指國際版的JDK,我們大多數程式設計師使用的是國際化的JDK版本,以下所有的JDK均指國際化的JDK版本。我們的漢字是雙位元組編碼語言,為了能讓電腦處理中文,我們自己制定的gb2312、GBK、GBK2K等標準以適應電腦處理的需求。
所以,大部分的作業系統為了適應我們處理中文的需求,均自訂有中文作業系統,它們採用的是GBK,GB2312編碼格式以正確顯示我們的漢字。如:中文Windows預設採用的是GBK編碼顯示,在中文Windows2000中儲存檔案時預設採用的儲存檔案的編碼格式也是GBK的,即所有在中文Windows2000中儲存的檔案它的內部編碼預設均採用GBK編碼,注意:GBK是在GB2312基礎上擴充的。
由於Java語言內部採用UNICODE編碼,所以在Java程式執行時,就存在著一個從UNICODE編碼和對應的作業系統及瀏覽器支援的編碼格式轉換輸入、輸出的問題,這個轉換過程有著一系列的步驟,如果其中任何步驟出錯,則顯示出來的漢字就會出是亂碼,這就是我們常見的Java中文問題。
同時,Java是一個跨平台的程式語言,也也就是我們寫的程式不僅能在中文windows上運行,也能在中文Linux等系統上運行,同時也要求能在英文等系統上運行(我們經常看到有人把在中文Windows2000上寫的Java程序,移植到英文Linux上運行)。這種移植操作也會帶來中文問題。
還有,有人使用英文的作業系統和英文的IE等瀏覽器,來運行帶有中文字符的程式和瀏覽中文網頁,它們本身就不支援中文,也會帶來中文問題。
幾乎所有的瀏覽器預設在傳遞參數時都是以UTF-8編碼格式來傳遞,而不是按中文編碼傳遞,所以,傳遞中文參數時也會有問題,從而帶來亂碼現象。
總之,以上幾個面向是Java中的中文問題的主要來源,我們把以上原因造成的程式無法正確運作而產生的問題稱作:Java中文問題。
2、Java編碼轉換的詳細流程
我們常見的Java程式包括以下類別:
*直接在console上運行的類別(包括可視化介面的類別)
*JSP程式碼類別(註:JSP是Servlets類別的變型)
*Servelets類別
* EJB類
*其它不可以直接運行的支援類
這些類文件中,都有可能含有中文字符串,並且我們常用前三類Java程序和用戶直接交互,用於輸出和輸入字符,如:我們在JSP和Servlet中得到客戶端送來的字符,這些字符也包括中文字符。無論這些Java類別的作用如何,這些Java程式的生命週期都是這樣的:
*程式設計人員在一定的作業系統上選擇一個合適的編輯軟體來實現原始程式碼並以.Java副檔名保存在作業系統中,例如我們在中文Windows2000中用記事本編輯一個Java原始程式。
*程式設計人員用JDK中的Javac.exe來編譯這些原始碼,形成.class類別(JSP檔案是由容器呼叫JDK來編譯的)。
*直接運行這些類別或將這些類佈署到WEB容器中去運行,並輸出結果。
那麼,在這些過程中,JDK和JVM是如何將這些檔案如何編碼和解碼並運行的呢?
這裡,我們以中文Windows2000作業系統為例說明Java類別是如何來編碼、被解碼的。
第一步,我們在中文Windows2000中用編輯軟體如記事本編寫一個Java源程序文件(包括以上五類Java程序),程序文件在保存時默認採用了操作系統默認支持GBK編碼格式(操作系統默認支持的格式為file.encoding格式)形成了一個.Java文件,也即,Java程式在被編譯前,我們的Java原始程式檔案是採用作業系統預設支援的file.encoding編碼格式儲存的,Java原始程式中含有中文資訊字元和英文程式碼;要查看系統的file.encoding參數,可以使用以下程式碼:
public class ShowSystemDefaultEncoding
{
public static void main(String[] args)
{
String encoding =
System.getProperty(”file.encoding”);
System.out.println(encoding);
}
}
第二步,我們用JDK的Javac.exe檔編譯我們的Java原始程序,由於JDK是國際版的,在編譯的時候,如果我們沒有用-encoding參數指定我們的Java原始程式的編碼格式,則Javac.exe先取得我們作業系統預設採用的編碼格式,也也就是在編譯Java程式時,若我們不指定原始程式檔案的編碼格式,JDK先取得作業系統的file.encoding參數(它儲存的就是作業系統預設的編碼格式,如Windows2000,它的值為GBK),然後JDK就把我們的Java原始程式從file.encoding編碼格式轉換為Java內部預設的UNICODE格式放入記憶體中。
然後,Javac把轉換後的unicode格式的文件進行編譯成.class類文件,此時.class文件是UNICODE編碼的,它暫放在內存中,緊接著,JDK將此以UNICODE編碼的編譯後的class檔案保存到我們的作業系統中形成我們見到的.class檔案。
對我們來說,我們最終獲得的.class檔案是內容以UNICODE編碼格式保存的類別文件,它內部包含我們原始程式中的中文字串,只不過此時它己經由file.encoding格式轉化為UNICODE格式了。
這一步驟中,對於JSP原始程式檔案是不同的,對於JSP,這個過程是這樣的:即WEB容器呼叫JSP編譯器,JSP編譯器先查看JSP檔案中是否設定有檔案編碼格式,如果JSP檔案中沒有設定JSP檔案的編碼格式,則JSP編譯器呼叫JDK先把JSP檔案用JVM預設的字元編碼格式(也即WEB容器所在的作業系統的預設的file.encoding)轉換為臨時的Servlet類,然後再把它編譯成UNICODE格式的class類,並保存在臨時資料夾中。
如:在中文Windows2000上,WEB容器就把JSP檔案從GBK編碼格式轉換為UNICODE格式,然後編譯成暫時儲存的Servlet類,以回應使用者的請求。
第三步,執行第二步編譯出來的類,分為三種情況:
A、 直接在console上運行的類別
B、 EJB類別和不可以直接運行的支援類別(如JavaBean類別)
C、 JSP程式碼和Servlet類別
D、 Java程式和資料庫之間
下面我們分這四種情況來看。
A、直接在console上執行的類別
這種情況,執行該類別首先需要JVM支持,即作業系統中必須安裝有JRE。運行過程是這樣的:首先Java啟動JVM,此時JVM讀出作業系統中保存的class檔案並把內容讀入內存中,此時內存中為UNICODE格式的class類,然後JVM運行它,如果此時此類需要接收使用者輸入,則類別會預設以file.encoding編碼格式對使用者輸入的字串進行編碼並轉換為unicode儲存入記憶體(使用者可以設定輸入流的編碼格式)。
程式執行後,產生的字串(UNICODE編碼的)再回交給JVM,最後JRE把此字串再轉換為file.encoding格式(使用者可以設定輸出流的編碼格式)傳遞給作業系統顯示介面並輸出到介面上。以上每一步的轉換都需要正確的編碼格式轉化,才能最終不出現亂碼現象。 B、EJB類和不可以直接運行的支援類(如JavaBean類)
由於EJB類和不可以直接運行的支持類,它們一般不與用戶直接交互輸入和輸出,它們常常與其它的類進行交互輸入和輸出,所以它們在第二步被編譯後,就形成了內容是UNICODE編碼的類別保存在作業系統中了,以後只要它與其它的類別之間的交互在參數傳遞過程中沒有丟失,則它就會正確的運行。
C、JSP程式碼和Servlet類別
經過第二步後,JSP檔案也被轉換為Servlets類別文件,只不過它不像標準的Servlets一校存在於classes目錄中,它存在於WEB容器的臨時目錄中,故這一步我們也把它做為Servlets來看。
對於Servlets,客戶端請求它時,WEB容器呼叫它的JVM來運行Servlet,首先,JVM把Servlet的class類別從系統中讀出並裝入記憶體中,記憶體中是以UNICODE編碼的Servlet類別的程式碼,然後JVM在記憶體中運行該Servlet類,如果Servlet在運行的過程中,需要接受從客戶端傳來的字元如:表單輸入的值和URL中傳入的值,此時如果程式中沒有設定接受參數時採用的編碼格式,WEB容器會預設採用ISO-8859-1編碼格式來接受傳入的值並在JVM中轉換為UNICODE格式的儲存在WEB容器的記憶體中。
Servlet運行後產生輸出,輸出的字串是UNICODE格式的,緊接著,容器將Servlet運行產生的UNICODE格式的串(如html語法,用戶輸出的串等)直接發送到客戶端瀏覽器上並輸出給用戶,如果此時指定了發送時輸出的編碼格式,則按指定的編碼格式輸出到瀏覽器上,如果沒有指定,則預設按ISO-8859-1編碼發送到客戶的瀏覽器上。
D、Java程序和資料庫之間
幾乎所有資料庫的JDBC驅動程序,預設的在Java程序和資料庫之間傳遞資料都是以ISO-8859-1為預設編碼格式的,所以,我們的程式在向資料庫當內部儲存包含中文的資料時,JDBC首先是把程式內部的UNICODE編碼格式的資料轉換為ISO-8859-1的格式,然後傳遞到資料庫中,在資料庫儲存資料時,它預設為以ISO-8859- 1保存,所以,這是為什麼我們常常在資料庫中讀出的中文資料是亂碼。
3.分析常見的Java中文問題幾個必須清楚的原則
首先,經過上面的詳細分析,我們可以清晰地看到,任何Java程序的生命期中,其編碼轉換的關鍵過程是在於:最初編譯成class文件的轉碼和最終向使用者輸出的轉碼過程。
其次,我們必須了解Java在編譯時支援的、常用的編碼格式有以下幾種:
*ISO-8859-1,8-bit, 同8859_1,ISO-8859-1,ISO_8859_1等編碼
*Cp1252,美國英語編碼,同ANSI標準編碼
*UTF-8,同unicode編碼
*GB2312,同gb2312-80,gb2312-1980等編碼
*GBK,同MS936,它是gb2312的擴充及其它的編碼,如韓文、日文、繁體中文等。同時,我們要注意這些編碼間的相容關系統如下:
unicode和UTF-8編碼是一一對應的關係。 GB2312可以認為是GBK的子集,即GBK編碼是在gb2312上擴展來的。同時,GBK編碼包含了20902個漢字,編碼範圍為:0×8140-0xfefe,所有的字元可以一一對應到UNICODE2.0中。
再次,對於放在作業系統中的.Java原始程式文件,在編譯時,我們可以指定它內容的編碼格式,具體來說用-encoding來指定。注意:如果原始程式中含有中文字符,而你用-encoding指定為其它的編碼字符,顯然是要出錯的。
用-encoding指定原始檔的編碼方式為GBK或gb2312,無論我們在什麼系統上編譯含有中文字元的Java原始程式都不會有問題,它都會正確地將中文轉換為UNICODE儲存在class檔案中。
然後,我們必須清楚,幾乎所有的WEB容器在其內部預設的字元編碼格式都是以ISO-8859-1為預設值的,同時,幾乎所有的瀏覽器在傳遞參數時都是預設以UTF-8的方式來傳遞參數的。
所以,雖然我們的Java原始檔在出入口的地方指定了正確的編碼方式,但其在容器內部運行時還是以ISO-8859-1來處理的。
4.中文問題的分類及其建議最優解決辦法
了解以上Java處理文件的原理之後,我們就可以提出了一套建議最優的解決漢字問題的方法。我們的目標是:我們在中文系統中編輯的含有中文字串或進行中文處理的Java源程式經編譯後可以移值到任何其它的作業系統中正確運行,或拿到其它作業系統中編譯後能正確運行,能正確地傳遞中文和英文參數,能正確地和資料庫交流中英文字串。我們的具體想法是:在Java程式轉碼的入口和出口及Java程式同用戶有輸入輸出轉換的地方限制編碼方法使其正確即可。
具體解決方法如下:
1、 針對直接在console上運行的類別
對於這種情況,我們建議在程式編寫時,如果需要從用戶端接收用戶的可能含有中文的輸入或含有中文的輸出,程式中應該採用字元流來處理輸入和輸出,具體來說,應用以下面向字符型節點流類型:
對檔案:FileReader,FileWrieter
其字節型節點流類型為:FileInputStream,FileOutputStream
對內存(數組):CharArrayReader,CharArrayWriter
其字節型節點流類型為:ByteArrayInputStream,ByteArrayOutputStream
對記憶體(字串):StringReader,StringWriter
對管道:PipedReader,PipedWriter
其位元組型節點流類型為:PipedInputStream,PipedOutputStream
同時,應該用下列字元型處理流類型處理輸入與輸出:
BufferedWriter,BufferedReader
其字節型的處理流為:BufferedInputeStream,BufferedOutputStream
InputStreamReader,OutputStreamWriter
其位元組型的處理流為:DataInputStream,
DataOutputStreamInputStreamReader和InputStreamWriter轉換到字元流,如:
InputStreamReader in = new InputStreamReader(System.in,”GB2312″); OutputStreamWriter out = new OutputStreamWriter (System.out,”GB2312″);例如:採用如下的示例編碼就達到了要求:
//Read.Java
import Java.io.*;
public class Read
{
public static void main(String[] args)
throws IOException
{
String str =
“n中文測試,這是內部硬編碼的串「+」ntest english character」;
String strin= “”;
BufferedReader stdin =
new BufferedReader(new
InputStreamReader(System.in,”gb2312″));
//設定輸入介面按中文編碼
BufferedWriter stdout =
new BufferedWriter(new
OutputStreamWriter(System.out,”gb2312″));
//設定輸出介面依中文編碼
stdout.write(”請輸入:”);
stdout.flush();
strin = stdin.readLine();
stdout.write(”這是從使用者輸入的字串:”+strin);
stdout.write(str);
stdout.flush();
}}
同時,在編譯程式時,我們用以下方式來進行:
Javac -encoding gb2312 Read.Java
2、針對EJB類別和不可以直接運行的支援類別(如JavaBean類別)
由於這種類別它們本身被其它的類調用,不直接與用戶交互,故對這種類來說,我們的建議的處理方式是內部程序中應該採用字符流來處理程序內部的中文字符串(具體如上面一節中一樣),同時,在編譯類別時用-encoding gb2312參數指示原始檔是中文格式編碼的即可。
3.針對Servlet類別
針對Servlet,我們建議用以下方法:
在編譯Servlet類別的源程式時,用-encoding指定編碼為GBK或GB2312,且在向使用者輸出時的編碼部分用response物件的setContentType(”text /html;charset=GBK”);或gb2312來設定輸出編碼格式,同樣在接收使用者輸入時,我們用request.setCharacterEncoding(”GB2312″);這樣無論我們的servlet類別移植到什麼作業系統中,只有客戶端的瀏覽器支援中文顯示,就可以正確顯示。如下是一個正確的範例:
//HelloWorld.Java
package hello;
import Java.io.*;
import Javax.servlet.*;
import Javax.servlet.http.*;
public class HelloWorld
extends HttpServlet
{
public void init()
throws ServletException
{
}
public void doGet
(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
request.setCharacterEncoding(”GB2312″);
//設定輸入編碼格式
response.setContentType
(”text/html;charset=GB2312″);
//設定輸出編碼格式
PrintWriter out = response.getWriter();
//建議使用PrintWriter輸出
out.println(”<hr>”);
out.println(”Hello World!
This is created by Servlet!測試中文!”);
out.println(”<hr>”);
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
request.setCharacterEncoding(”GB2312″);
//設定輸入編碼格式
response.setContentType
(”text/html;charset=GB2312″);
//設定輸出編碼格式
String name = request.getParameter(”name”);
String id = request.getParameter(”id”);
if(name==null) name=”";
if(id==null) id=”";
PrintWriter out = response.getWriter();
//建議使用PrintWriter輸出
out.println(”<hr>”);
out.println(”你傳入的中文字符串是:” + name);
out.println(”<hr>你輸入的id是:” + id);
out.println(”<hr>”);
}
public void destroy()
{
}
}
請用Javac -encoding gb2312 HelloWorld.Java來編譯此程式。
測試此Servlet的程式如下所示:
< %@page contentType=”text/html;
charset=gb2312″%>
<%request.setCharacterEncoding(”GB2312″);%>
<html><head><title></title>
<Script language=”JavaScript”>
function Submit()
{
//透過URL傳遞中文字串值給Servlet
document.base.action =
“./HelloWorld?name=中文”;
document.base.method = “POST”;
document.base.submit();
}
</Script>
</head>
<body bgcolor=”#FFFFFF”
text=”#000000″ topmargin=”5″>
<form name=”base” method =
“POST” target=”_self”>
<input name=”id” type=”text”
value=”" size=”30″>
<a href = “JavaScript:Submit()”>
傳給Servlet</a>
</form></body></html>
4.Java程式與資料庫之間
為避免Java程式與資料庫之間資料傳遞出現亂碼現象,我們建議採用以下最優方法來處理:
1、對於Java程式的處理方法依我們指定的方法處理。
2.把資料庫預設支援的編碼格式改為GBK或GB2312的。
如:在mysql中,我們可以在設定檔my.ini中加入以下語句實作:
在[mysqld]區增加:
default-character-set=gbk
並增加:
[client]
default-character-set=gbk
在SQL Server2K中,我們可以將資料庫預設的語言設定為Simplified Chinese來達到目的。
5.針對JSP程式碼
由於JSP是在執行時,由WEB容器進行動態編譯的,如果我們沒有指定JSP原始檔的編碼格式,則JSP編譯器會取得伺服器作業系統的file.encoding值來對JSP檔編譯的,它在移植時最容易出問題,如在中文Windows2000中可以很好運行的jsp文件拿到英文linux中就不行,儘管客戶端都是一樣的,那是因為容器在編譯JSP文件時獲取的作業系統的編碼不同造成的(在中文wink中的file.encoding和在英文Linux中file.encoding是不同的,而英文Linux的file.encoding對中文不支持,所以編譯出來的JSP類就會有問題)。
網路上討論的大多數是這類問題,多是因為JSP檔案移植平台時無法正確顯示的問題,對於這類問題,我們了解了Java中程式編碼轉換的原理,解決起來就容易多了。我們建議的解決方法如下:
1、我們要保證JSP向客戶端輸出時是採用中文編碼方式輸出的,即無論如何我們首先在我們的JSP源代編中加入以下一行:
< %@page contentType=” text/html;
charset=gb2312″%>
2.為了讓JSP能正確獲得傳入的參數,我們在JSP原始檔頭加入下面一句:
<%request.setCharacterEncoding(”GB2312″);
%>
3.為了讓JSP編譯器能正確地解碼我們的含有中文字元的JSP文件,我們需要在JSP原始檔中指定我們的JSP原始檔的編碼格式,具體來說,我們在JSP原始檔頭上加入下面的一句即可:
< %@page pageEncoding=”GB2312″%>
或< %@page pageEncoding=”GBK”%>
這是JSP規格2.0新增加的指令。
我們建議使用此方法來解JSP檔案中的中文問題,下面的程式碼是一個正確做法的JSP檔案的測試程式:
//testchinese.jsp
< %@page pageEncoding=”GB2312″%>
< %@page contentType=”text/html;
charset=gb2312″%>
<%request.setCharacterEncoding(”GB2312″);
%>
<%
String action = request.getParameter(”ACTION”);
String name = “”;
String str = “”;
if(action!=null && action.equals(”SENT”))
{
name = request.getParameter(”name”);
str = request.getParameter(”str”);
}
%>
<html>
<head>
<title></title>
<Script language=”JavaScript”>
function Submit()
{
document.base.action =
“?ACTION=SENT&str=傳入的中文”;
document.base.method = “POST”;
document.base.submit();
}
</Script>
</head>
<body bgcolor=”#FFFFFF”
text=”#000000″ topmargin=”5″>
<form name=”base” method =
“POST” target=”_self”>
<input type=”text” name=”name”
value=”" size=”30″>
<a href = “JavaScript:Submit()”>提交</a>
</form>
<%
if(action!=null && action.equals(”SENT”))
{
out.println(”<br>你輸入的字元為:”+name);
out.println(”<br>你透過URL傳入的字元為:”+str);
}
%>
</body>
</html>