java learnging

          一塊探討JAVA的奧妙吧
          posts - 34, comments - 27, trackbacks - 0, articles - 22

          和Java一樣,JSP是目前比較熱門的一個話題。它是一種在服務器端編譯執行的Web設計語言,因為腳本語言采用了Java,所以JSP繼承了Java的所有優點??墒窃谑褂肑SP程序的過程中,常遇到中文亂碼問題,很多人為此頭疼不已,筆者就深受其害,而且使用平臺不同,中文亂碼問題的解決方法也不同,無形中增加了學習JSP的難度。其實,在徹底了解相關原因后,問題還是比較容易解決的。筆者結合自己的工作實踐,對中文顯示問題進行了一定的研究,并在不同的環境下進行了相關測試,以下是筆者總結的解決方法,相信對讀者會有一定的借鑒意義。


          JSP中文亂碼問題的解決
          ● 彭文波


          --------------------------------------------------------------------------------

          字符內碼
          每個國家(或區域)都規定了計算機信息交換用的字符編碼集,如美國的擴展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中附帶中文參數。這里中文參數通??梢灾苯幼x取,例如: <%= 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


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 青神县| 四子王旗| 保亭| 定日县| 凤凰县| 宁夏| 双牌县| 宁强县| 武山县| 新河县| 德令哈市| 雷山县| 泗水县| 巴马| 韶关市| 梅河口市| 萨迦县| 六安市| 双柏县| 尚志市| 泌阳县| 库车县| 望奎县| 比如县| 三河市| 仙居县| 夏邑县| 襄城县| 屯昌县| 桑植县| 大埔县| 周至县| 古蔺县| 祁阳县| 黎川县| 南阳市| 东至县| 石楼县| 南溪县| 郎溪县| 固原市|