JSP中文亂碼問題的解決

來源:互聯網
上載者:User
js|解決|問題|中文|中文亂碼  

字元內碼
每個國家(或地區)都規定了電腦資訊交換用的字元編碼集,如美國的擴充ASCII碼、中國的GB2312-80、日本的 JIS 等,作為該國家(地區)資訊處理的基礎,有著統一編碼的重要作用。由於各本地字元集代碼範圍重疊,相互間資訊交換困難,軟體語言版本獨立維護成本較高。因此有必要將本地化工作中的共性抽取出來,做一致性處理,將特殊的本地化處理內容降低到最少,這就是所謂的國際化(I18N)。各種語言資訊被規範為本地資訊,而底層字元集採用包含了所有字元的Unicode。

字元內碼(character code)指的是用來代表字元的內碼。我們在輸入和儲存文檔時都要使用內碼,內碼分為單位元組內碼和雙位元組內碼。單位元組內碼的英文全稱是Single-Byte Character Sets (SBCS),可以支援256個字元編碼;雙位元組內碼的英文全稱是Double-Byte Character Sets(DBCS),可以支援65000個字元編碼,主要用來對大字元集的東方文字進行編碼。

CodePage指的是一個經過挑選的以特定順序排列的字元內碼列表,對於早期的單位元組內碼的語種,CodePage中的內碼順序使得系統可以按照此列表來根據鍵盤的輸入值給出一個對應的內碼。對於雙位元組內碼,給出的是MultiByte到Unicode的對應表,這樣就可以把以Unicode形式存放的字元轉化為相應的字元內碼。引入對CodePage的支援主要是為了訪問多語種檔案名稱,目前在NTFS和FAT32/VFAT下的檔案系統上都使用Unicode,這需要系統在讀取這些檔案名稱時動態地將其轉換為相應的語言編碼。

相信瞭解JSP代碼的讀者對ISO8859-1一定不陌生,ISO8859-1是我們平時使用比較多的一個CodePage,它屬於西歐語系。GB2312-80 是在國內電腦漢字資訊技術發展初始階段制訂的,其中包含了大部分常用的一、二級漢字和9區的符號。該字元集是幾乎所有的中文系統和國際化的軟體都支援的中文字元集,這也是最基本的中文字元集。

GBK 是 GB2312-80 的擴充,是向上相容的。它包含了20902個漢字,其編碼範圍是 0x8140~0xFEFE,剔除高位 0x80 的字位,其所有字元都可以一對一映射到 Unicode 2.0,也就是說 Java 實際上提供了對 GBK 字元集的支援。

>GB18030-2000(GBK2K) 在 GBK 的基礎上進一步擴充了漢字,增加了藏、蒙等少數民族的文字。GBK2K 從根本上解決了字位不夠、字形不足的問題。


不同開發平台的區別
1.Tomcat 4開發平台

Windows 98/2000下的Tomcat 4以上版本都會出現中文問題(而在Linux下和Tomcat 3.x中則沒有問題),主要表現是頁面顯示亂碼。在IE中調整字元集為GB2312,就可以正常顯示了。

為解決這個問題,可在每個JSP的頁面開始處加上<%@ page language=“Java” contentType=“text/html; charset=gb2312”%>。不過,這還不夠,雖然這時顯示了中文,但是發現從資料庫讀出的欄位變成了亂碼。經過分析發現: 在資料庫中儲存的中文字元是正常的,資料庫用ISO8859-1字元集存取資料,而Java程式在處理字元時預設採用統一的ISO8859-1字元集(這也體現了Java國際化思想),所以在資料添加的時候Java和資料庫都是以ISO8859-1方式處理,這樣不會出錯。但是在讀取資料的時候就出現問題了,因為資料讀出也採用ISO8859-1字元集,而 JSP的檔案頭中有語句<%@ page language=“Java” contentType=“text/html; charset=gb2312”%>,這說明頁面採用GB2312的字元集顯示,這樣就和讀出的資料不一樣。這時頁面顯示從資料庫中讀出的字元是亂碼,解決的方法是對這些字元轉碼,從ISO8859-1轉成GB2312,就可以正常顯示了。這個解決辦法對很多平台具有通用性,讀者可以靈活運用。

2.Tomcat 3.x、Resin及Linux平台

在Tomcat 3.x、Resin中或是在Linux下,沒有加入語句<%@ page language=“Java” contentType=“text/html; charset=gb2312”%>,而頁面中的<meta http-equiv=“Content-Type” content=“text/html; charset=gb2312”>語句起了作用,此時可以正常顯示。相反,如果加上<%@ page language=“java” contentType=“text/html; charset=gb2312”%>系統會報錯,說明Tomcat 4以上版本的引擎在處理JSP時還是有差別的。

另外,對於不同的資料庫如SQL Server,Oracle,Mysql,Sybase等,字元集的選擇很重要。如果考慮多語言版本,資料庫的字元集就應該統一採用ISO8859-1,需要輸出的時候在不同的字元集之間做轉換就可以了。

以下是針對不同平台的總結:

(1) JSWDK只適合於普通開發,穩定性和其他問題可能不如商業軟體。 由於JDK 1.3版效能要好於JDK 1.2.2很多,並且對中文的支援也較好,所以應該盡量採用。

(2) 作為免費的商業軟體,Resin不僅速度快、穩定、自動編譯,還可以指出出錯行,並可在伺服器端支援使用JavaScript等,而且對中文的支援也很好。

(3) Tomcat僅僅是一個對JSP 1.1、Servlet 2.2標準的實現, 我們不應該要求這個免費軟體在細節和效能上都面面俱到, 它主要考慮英文使用者, 這也是為什麼不做特殊轉換,漢字用URL方法傳遞就有問題的原因。大部分IE瀏覽器預設始終以UTF-8發送, 這似乎是Tomcat的一個不足, 另外Tomcat不管當前的作業系統是什麼語言, 都按ISO8859去編譯JSP, 似乎也欠妥。


JSP代碼的中文處理
在JSP代碼中以下幾處經常需要涉及到中文處理:

1. 在URL中附帶中文參數。這裡中文參數通常可以直接讀取,例如: <%= request.getParameter(“showword”)%>

2. 在JSWDK中讀取HTML表單提交的中文值這時需要加以編碼,較為簡潔的寫法是:

String name1=new String(request.getParameter(“user_id”).getBytes(“ISO8859_1”))。

另外,在JDK 1.3的支援下,不需加入<%@ page contentType=“text/html;charset=gb2312”%> ,而在JDK 1.2.2 以下,即使以上兩種方法同時運用也很不穩定。但在Resin平台,情況較好,只要在頁面第一行加入:<%@ page contentType=“text/html;charset=gb2312”%>即可正確處理中文,如果再加代碼則反而不對。

3.在JSWDK中Session包含的中文,如果從表單中讀出的值經過編碼可正確顯示,但直接賦予中文值則不行,而Resin平台則很好。

4. 在編譯Servlet和JSP時加入代碼選項。在編譯Servlet時使用Java-Encoding ISO8859-1 myservlet.java;在JSP的ZONE設定檔中,修改編譯參數為:Compiler=builtin - javac- encoding ISO8859-1。使用這種方法後,不需要做其他的改動就可以正常顯示中文了。

另外,流行的關聯式資料庫系統都支援資料庫Encoding,也就是說在建立資料庫時可以指定它自己的字元集設定,資料庫的資料以指定的編碼形式儲存。當應用程式訪問資料時,在入口和出口處都會有 Encoding 轉換。對於中文資料,資料庫字元編碼的設定應當保證資料的完整性。 GB2312、GBK、UTF-8 等都是可選的資料庫 Encoding,也可以選擇 ISO8859-1 (8-bit), 但會增加了編程的複雜度,ISO8859-1不是推薦的資料庫 Encoding。在JSP/Servlet編程時,可以先用資料庫管理系統提供的管理功能檢查其中的中文資料是否正確。


處理方法執行個體
下面是兩個具體的中文亂碼解決執行個體,讀者仔細研究後可能會有所收穫。

1.常見的字元轉換方法

將Form 中 的 值 傳 送 到 數 據 庫 中 再 取 出 來 後 全 變 成 了“?”。Form用POST提交資料,代碼中使用了語句:String st=new(request.getParameter(“name”).getBytes(“ISO8859_1”)), 而且也聲明了charset=gb2312。

要處理Form中傳遞的中文參數,應該在JSP中加入下面的代碼,另外定義一個專門解決這個問題的getStr類,然後對接收到的參數進行轉換:
String keyword1=request.getParameter(“keyword1”);
keyword1=getStr(keyword1);
這樣就可以解決問題了,代碼如下:
<%@ page contentType=“text/html;charset=gb2312”%>
<%!
public String getStr(String str){
try{String temp_p=str;
byte[] temp_t=temp_p.getBytes(“ISO8859-1”);
String temp=new String(temp_t);
return temp;
}
catch(Exception e){ }
return “NULL”;
}
%>
<%--http://www.cndes.com測試--%>
<% String keyword=“創連網絡技術中心歡迎您的到來”;
String keyword1=request.getParameter(“keyword1”);
keyword1=getStr(keyword1);
out.print(keyword);
out.print(keyword1);
%>

2. JDBC Driver的字元轉換

目前大多數JDBC Driver採用本地編碼格式來傳輸中文字元,例如中文字元“0x4175”會被轉成“0x41”和“0x75”進行傳輸。因此需要對JDBC Driver返回的字元以及要發給JDBC Driver的字元進行轉換。當用JDBC Driver向資料庫中插入資料時,需要先將Unicode轉成Native code; 當 JDBC Driver從資料庫中查詢資料時,則需要將Native code轉換成Unicode。下面給出了這兩種轉換的實現:
String native2Unicode(String s) {
if (s == null || s.length() == 0) {
return null;
}
byte[] buffer = new byte[s.length()];
for (int i = 0; i s.length(); i++) { if (s.charAt(i)>= 0x100) {
c = s.charAt(i);
byte []buf = (“”+c).getBytes();
buffer[j++] = (char)buf[0];
buffer[j++] = (char)buf[1];
}
else {buffer[j++] = s.ch




相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.