| 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,DataOutputStream 其中InputStreamReader和InputStreamWriter用於將字節流按照指定的字符編碼集轉換到字符流,如: InputStreamReader in = new InputStreamReader(System.in,"GB2312"); OutputStreamWriter out = new OutputStreamWriter (System.out,"GB2312"); 例如:採用如下的示例JAVA編碼就達到了要求:
//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 其運行結果如圖5所示:

圖5 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> 其運行結果如圖6所示:

圖6 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文件編譯的,它在移植時最容易出問題,如在中文win2k中可以很好運行的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> 如圖7是此程序運行的結果示意圖:

圖7
5、總結
在上面的詳細分析中,我們清晰地給出了JAVA在處理源程序過程中的詳細轉換過程,為我們正確解決JAVA編程中的中文問題提供了基礎。同時,我們給出了認為是最優的解決JAVA中文問題的辦法。
6、參考資料 1、段明輝.Java 編程技術中漢字問題的分析及解決. http://www-900.ibm.com/developerWorks/cn/java/java_chinese/index.shtml 2、 周競濤.關於Java中文問題的幾條分析原則 http://www-900.ibm.com/developerWorks/cn/java/l-javachinese/index.shtml
|