有關中文轉碼的幾個基本問題

以下是我在最近的實踐中的總結,寫給做J2EE web開發中遇到中文問題的初學者,箇中高手就不需過目了。
文中舉到的例子取自我自己參與的項目。我是在簡體系統下開發繁體web。

網頁向servlet傳遞中文參數的轉碼過程

一. 在網頁的輸入框中鍵入中文字符串,點擊提交。

二. 瀏覽器將鍵入的中文字符串A編碼成字節流A,提交給服務器. (瀏覽器編碼的方式採用的瀏覽器設定的編碼,如IE6中即爲"菜單:查看->編碼"中指定的編碼,下面以MS950爲例)。

三. 服務器得到字節流A後,將其按ISO8859_1(默認)解碼爲字符串B。具體可分爲以下兩步。
         1. 用ISO8859_1的編碼規則解釋傳入的字節流A。得到字符串B。
  2. 將解釋後的字符串B用UNICODE編碼,放在內存中。
  servlet程式中用request.getParameter("paraName");得到的便是這樣的字符串。
  以上可以看出,此時服務器並不知道客戶端瀏覽器發送的字節流是用什麼方式編碼的,而統一以ISO8859_1來解釋傳入的以MS950編碼的字節流A,此時解釋出來的字符串B自然是與網頁中輸入的字符串A是不同的,也就是錯誤的。此時無論如何輸出,得到的都會是亂碼。

四. 瞭解了上述過程,要使servlet得到正確的字符串A,原理就是將上述過程還原。具體步驟如下:
 1. String sPara = request.getParameter("paraName");得到上述“錯誤”的字符串B。
 2. byte bPara = sPara.getBytes("ISO8859_1");得到字節流A,以上還原過程三.1。
 3. String sPara = new String(bPara,"MS950");得到字符串A,以上還原過程二。

此時sTmpParaName中保存的就是以UNICODE編碼的正確的字符串了。servlet對此字符串一般會有兩種操作:讀寫數據庫或向客戶端輸出。

五. JAVA程式通過JDBC連接器與數據庫進行數據交互,交互過程都是以ISO8859_1編碼的字節流進行的。以下舉例將sPara插入數據庫。
 1.執行 UPDATE INTO TBNAME SET COLNAME := :sPara
 2JAVA程將此SQL語句中的sPara字符串按ISO8859_1編碼成字節流,發送給JDBC連接器,JDBC連接器再將此字節流發送給數據庫。數據庫再根據ISO8859_1方式將此字節流還原爲字符串,並將字符串寫入數據庫中。字符串在數據庫中的存儲編碼方式與數據庫設置有關(以UTF8爲例)。
 以上可以看出,JDBC傳輸字節流的過程對用戶來說是透明的。無論數據庫中用何種編碼存放,只要保證SQL語句中是“正確”的字符串,就可以正確無誤的寫入數據庫。不需做任何轉碼。
 當JAVA程式從數據庫中讀取字符串時,有兩種方式,一種是直接讀出字符串,用sMsg = ResultSet.getString("colName");另一種是讀出字節數組,用bMsg = ResultSet.getBytes("colName");前一種直接得到字符串,後一種要得到字符串需要知道數據庫的存儲編碼方式,如:sMsg = new String(bMsg, "utf-8"));。

向客戶端輸出字符串時,服務器是根據servlet或JSP中的設置,將字符串轉碼爲字節流向瀏覽器發送的。在JSP中通過<%@page contentType="text/html; charset=MS950"%>設置,在servlet程式中通過response.setContentType("text/html;charset=MS950"); 設置。
 客戶想要看到正常顯示的網頁,只要讓瀏覽器的編碼設置和上述設置一致,或者兼容即可。如沒有上述設置,剛服務器默認以ISO8859_1方式編碼後向客戶端輸出,由於ISO8859_1是單字節編碼,無法編碼中文字,因而在編碼過程中已經失真,因此是無法在瀏覽器中正確顯示的。


關於文字的字節數:
要得到正確的字節數,即字符串存儲的大小,關鍵有以下兩點。
 1. 正確的字符串,在JAVA中保證UNICODE字符串是真正需要的字符串。
 2. 確定的編碼方式,不同的編碼方式中,同一漢字所佔的字節數可能是不同的。
 如,我們要得到字符串sPara的MS950編碼的字節數,可分以下兩步。
  1.得到正確的sPara字符串,參考過程四。
  2.bPara = sPara.getBytes("MS950");得到MS950編碼。
  3.bPara.length得到字節數。
 如果不指定編碼方式,談論字符串的字節數是沒有意義的。


補充:在JAVA中,字符串對象使終是以UNICODE在內存中存放的,而在數據庫,文件,網絡傳輸,瀏覽器中則有不同的編碼和存儲方式,因些。在遇到中文內碼問題時,最方便的思考辦法就是以UNICODE字符串爲中心,然後確認需要將字符串與字節流或數組進行轉換的編碼方式。

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/javaflute/archive/2005/02/04/280398.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章