亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

實現J2EE中的多字節字符處理(組圖)

2019-11-18 12:24:00
字體:
來源:轉載
供稿:網友

  中文是世界上最復雜、最完備的語言之一。有時我會為自己是個中國人而感到幸運,非凡是當我看到我的一些外國朋友為學習這門語言(尤其是寫漢字)而絞盡腦汁的時候??僧斘矣肑2EE開發本地化Web應用時,又會感到很不幸。下面我就說說為什么。
  
  盡管java平臺和大多數J2EE服務器都能很好地支持國際化,我在開發中文或日文應用時仍會碰到許多有關多字節字符方面的問題:
  
  ·編碼和字符集之間有什么區別?
  ·為什么多字節字符應用從一種操作系統遷移到另一種上時顯示會有差異?
  ·為什么多字節字符應用從一種應用服務器遷移到另一種上時顯示會有差異?
  ·為什么我的多字節字符應用在IE瀏覽器里顯示正常,可到了Mozila瀏覽器里卻又不行?
  ·為什么以UTF-16(通用轉換格式)編碼的應用在大多數J2EE服務器上都不能很好地顯示?
  
  假如你也有同樣的問題,本文將有助于你找到答案。
  
  字符的基礎知識
  
  字符在計算機出現之前就早已存在。大約3,000年前,古代中國就出現了一些非凡的文字符號(即甲骨文)。這些文字符號有特定的外形和含義,它們中的大部分都有名字和發音。所有這些文字符號匯集成了字碼表,一套從屬于特定語言的獨特字符集合,它們與計算機沒有任何關系。幾千年過去了,許多語言都在發展,數以千計的字符被創造出來。如今我們要將所有這些字符都數字化為0和1,這樣計算機才能理解它們。
  
  用鍵盤輸入單詞的時候要用到字符輸入法。對于簡單的字符,鍵盤和字符間存在著一對一的映射關系;而對于較復雜的語言,需要多次敲擊鍵盤才能輸入一個字符。
  
  在你能從屏幕上看到字符之前,操作系統必須先將字符存放在內存里。實際上操作系統在字碼表的字符與一系列非負整數之間定義了一一對應的關系,它們被存放在內存里并被操作系統調用,這些整數被稱為字符代碼。
  
  字符可以用文件存儲或通過網絡傳輸。軟件用字符編碼來定義每個字符的字符代碼與八進制序列數之間的對應方法(算法)。有些字符代碼對應一個字節,如ASCII碼;還有一些字符代碼需要對應兩個或更多的字節(如中文和日文),這種對應關系依靠于不同的字符編碼方式。
  
  不同的語言使用不同的字碼表,每個字碼表都有一些特定的編碼方式。在某些情況下,當你選用某種語言時就已經不自覺地選擇了某種字符編碼方式。例如當你選用中文的時候,在默認情況下你用的可能就是GBK中文字碼表及稱作GBK的特定字符編碼方式。
  
  為了不致混淆,我避免使用字符集這個詞。顯然,字符集與字碼表是同義詞。字符集在HTTP Mime(多用途網際郵件擴充協議)頁頭里被誤用,其實這里的“charset(字符集)”是指“encoding(編碼)”。
  
  Java的特征之一是字符是16位的,這樣就能支持Unicode(一種表示各種語言中許多不同種類的字符的標準方式)。不幸的是,這個特征在開發多字節J2EE應用中也引發了許多問題,本文將就此進行討論。
  
  開發階段引起的顯示問題
  
  J2EE應用開發包括若干個階段(如圖1所示),每個階段都可能導致多字節字符顯示問題。
  
 實現J2EE中的多字節字符處理(組圖)(圖一)
  圖1 J2EE應用開發生命周期

  
  編碼階段
  
  當你開始J2EE應用編碼時,大多數情況下你會用JBuilder、NetBean之類的IDE,或者是UltraEdit、Vi之類的編輯器。無論你選擇了哪一個,只要在jsp(JavaServer Pages)、Java或Html文件中有文字字符串,而且這些字符串是像中文或日文這樣的多字節字符,那么你要是不小心的話就很可能會碰到顯示問題。
  
  文字字符串是存儲于文件中的靜態信息,不同語言的字符采用不同的編碼方式。大多數IDE的默認編碼方式是ISO-8859-1,這種編碼方式適合ASCII字符,但會使多字節字符丟失信息。例如,中文版的NetBean在對文件編碼時其默認編碼方式就不幸為ISO-8859-1。在我編寫帶有中文字符的JSP文件時(如圖2所示),看上去一切正常。我前面提到,屏幕上顯示的所有字符都在內存中,與編碼方式沒有直接的關系。在保存文件后,假如關閉IDE再重新打開,這些字符就顯示為亂碼(如圖3所示),這是因為ISO-8859-1編碼方式在存儲中文字符時會丟失一些信息。
  
 實現J2EE中的多字節字符處理(組圖)(圖二)
  圖2 NetBeans里的中文字符
   實現J2EE中的多字節字符處理(組圖)(圖三)
  圖3 中文字符成了亂碼

  
  字符編碼API
  
  在servlet和JSP規范里有幾個API用來控制J2EE應用的字符編碼過程。對于servlet請求,setCharacterEncoding()方法對當前HTTP請求設定編碼方式;對于servlet響應,setContentType()方法和setLocale()方法對HTTP響應輸出設置Mime頭的編碼方式。
  
  這些API本身不會引發問題,但假如你忘了用它們就有問題了。例如在有些服務器上你可以正確無誤地顯示多字節字符而不必在代碼中使用上述的任何一個API,但在其它的服務器上運行應用時字符卻變成了亂碼。多字節字符顯示問題的成因在于服務器在處理HTTP請求和響應期間如何對字符進行編碼。以下是服務器確定請求和響應的編碼方式的規則,對大多數服務器都適用:
  
  在處理servlet請求時,服務器按以下次序(自上而下)來確定請求的字符編碼方式:
  
  ·代碼中指定的設置(如setCharacterEncoding()方法中指定的編碼方式)
  ·廠商的初始設置
  ·默認的設置
  
  在處理servlet響應時,服務器按以下次序(自上而下)來確定響應的字符編碼方式:
  
  ·代碼中指定的設置(如setContentType() 方法和setLocale()方法中指定的編碼方式)
  ·廠商的初始設置
  ·默認的設置
  
  按照上述規則,假如在代碼中用API進行了指定,所有的服務器都會按指定的字符編碼方式編碼,否則服務器就會各行其道。有些廠商用HTTP表單的隱藏字段(hidden fields)來確定請求的編碼方式,還有些廠商則采用它們自己配置文件中的特定設置。即使是默認設置也不盡相同,大多數廠商采用ISO-8859-1作為默認設置,還有少數廠商采用操作系統的本地設置值。因此,一些帶有多字節字符的應用在遷移到另一個廠商的J2EE服務器上時就會出現顯示問題。
  
  編譯階段
  
  假如設置正確,在編輯的時候就能在源文件中存儲多字節的文字字符串,但這些源文件不能直接執行。假如編寫的是servlet代碼,這些Java文件在部署到應用服務器之前必須先被編譯成類文件。對于JSP文件,應用服務器在執行前會自動將其編譯成類文件。在編譯階段,字符編碼問題仍有可能存在。為了運行下面這個簡單示例,請下載本文的源代碼。
  
  程序清單1 EncodingTest.java
  1   import java.io.ByteArrayOutputStream;
  2   import java.io.OutputStreamWriter;
  34   public class EncodingTest {
  5public static void main(String[] args) {
  6OutputStreamWriter out = new OutputStreamWriter(new ByteArrayOutputStream());
  7   System.out.  8      System.out.println("Literal output: ??o?£?");
  // You may not see this Chinese String
  9}
  10   }
  
  有關這段源代碼的說明如下:
  ·?    我們用下面的代碼確定系統當前的編碼方式:
  6  OutputStreamWriter out = new OutputStreamWriter(new ByterrayOutputStream());
  7  System.out.println("Current Encoding: "+out.getEncoding());
  ·第8行包含直接打印輸出中文文字字符串(由于操作系統語言設置的原因可能造成該字符串不能正常顯示)的代碼。
  ·用GBK編碼方式保存這個Java源文件。
  
  執行結果如圖4所示。
  
 實現J2EE中的多字節字符處理(組圖)(圖四)
  圖4 示例程序的輸出。

  
  從圖4的執行結果中我們可以歸納出:
  
  ·Java編譯器(javac)將系統的語言環境作為默認的編碼設置,Java運行時(Java Runtime Environment.)也如此。
  ·只有第一次的運行結果是正確的,其它的字符串顯示都有問題。
  ·僅當運行時的編碼設置與源文件保存時的編碼方式相一致時才能正確顯示多字節文字字符串(否則就必須進行轉碼,參見“運行時階段”部分)。
  
  服務器配置階段
  
  在運行J2EE應用之前,一般會根據特定的需要對應用進行配置。在上一節中,我們發現不同的語言設置會導致文字字符串顯示出問題。實際上配置存在于不同的層面,它們都可能會引發多字節字符問題。
  
  操作系統層
  
  操作系統對語言的支持非常重要。前面提到服務器端對語言的支持會影響JVM默認的編碼設置,而在客戶端的語言支持(如
字體)也能直接影響字符的顯示,但這不是本文要討論的重點。
  
  J2EE應用服務器層
  
  大多數服務器都有一個基本服務器設置,可用來配置默認的字符編碼處理方式。清單2就是Tomcat配置文件的一部分(位于$TOMCAT_HOME/conf/web.xml)。
  
  清單2 web.xml
  <servlet>
  <servlet-name>jsp</servlet-name>
  <servlet-class>org.apache.jASPer.servlet.JspServlet</servlet-class>
  <init-param>
  <param-name>fork</param-name>
  <param-value>false</param-value>
  </init-param>
  <init-param>
  <strong>
  <param-name>javaEncoding</param-name>>
  <param-value>>UTF8</param-value>
  </strong>
  </init-param>
  <load-on-startup>3</load-on-startup>
  </servlet>
  
  Tomcat以參數javaEncoding來確定從JSP文件生成Java源文件的Java文件編碼方式。這里的默認值是UTF-8,這意味著假如JSP文件中的中文字符以GBK編碼保存,將會以UTF-8編碼(瀏覽器端設置)顯示,在這種情況下就可能會出問題。
  
  JVM層
  
  大多數服務器都答應同時運行多個實例,且每個服務器實例都能有自己的JVM實例。此外,還可對每一個JVM實例分別設置。大多數服務器用本地設置來為每個實例定義默認的語言支持。
  
 實現J2EE中的多字節字符處理(組圖)(圖五)
  圖5 Sun ONE 應用服務器設置

  
  圖5顯示的是Sun ONE(開放網絡環境)應用服務器的一個本地單個實例設置。該設置給出了登錄系統和標準輸出的默認字符編碼方式。
  
  此外,不同的服務器使用的JVM版本可能會不同,而不同的JDK版本支持的編碼標準各異,所有這些都會導致遷移問題。例如Sun ONE應用服務器與Tomcat都支持J2SE 1.4,而有些服務器只支持到J2SE 1.3。J2SE 1.4支持Unicode 3.1,它具有許多早期版本所沒有的新特性。
  
  單個應用層
  
  每個部署在服務器上的應用在運行前都可以為其配置獨立的編碼設置,這就使得在同一個服務器實例上能夠運行多個采用不同語言的應用。一些服務器用以下的字符編碼設置為每個部署的應用指定其應使用的編碼方式:
  
  <locale-charset-info default-locale="en_US">
  </locale-charset-map locale="zh_CN" agent="Mozilla/4.77 [en] (Windows NT 5.0; U)"
  charset="GBK"></locale-charset-info>
  
  這種分層配置的目的是為了靈活性和可維護性。但不幸的是,當在服務器間遷移時這種做法就可能導致出問題,因為并非所有的服務器配置都遵循標準。比如說,假如在一個支持本地字符集設置的服務器上開發了應用,那么當把該應用遷移到另一個不支持這種編碼設置的服務器上時就可能會碰到問題。
  
  運行時階段
  
  在運行過程中J2EE應用很可能會與其它外部系統通信。應用也許會讀寫文件,或者用數據庫治理數據,有時候還可能用LDAP(輕量目錄訪問協議)服務器存儲標識信息。在這些情況下,J2EE應用和外部系統之間需要進行數據交換。假如數據中帶有象中文這樣的多字節字符,就可能會碰到問題。
  
  大部分的外部系統都有他們自己的編碼設置。例如LDAP服務器很可能使用UTF-8對字符編碼;Oracle數據庫系統用環境變量NLS_LANG來指定編碼方式。假如Oracle是安裝在中文操作系統上,該變量的默認設置為ZHS16GBK,也就是用GBK編碼方式來存儲中文字符。因此當J2EE應用的編碼設置與外部系統不同時需要進行轉碼,通常用以下代碼來完成這一工作:
  
  byte[] defaultBytes = original.getBytes(current_encoding);
  String newEncodingStr = new String(defaultBytes, old_encoding);
  
  以上代碼給出了如何將字符串從一種編碼方式轉換為另一種。例如你在LDAP服務器中用UTF-8編碼存儲了一個用戶名(多字節字符),而在J2EE應用中用的卻是GBK編碼,因此當應用從LDAP服務器中取用戶名時就可能被錯誤地編碼。要解決這個問題,可以用original.getBytes("GBK")得到原始的字節,然后用new String(defaultBytes, "UTF-8")構造一個新字符串,這樣就可以正確顯示了。
  
  客戶端顯示階段
  
  現在大多數J2EE應用都采用瀏覽器/服務器架構,以瀏覽器作為客戶端。要在瀏覽器里正確顯示多字節字符,需要注重以下幾個方面:
  
  瀏覽器語言支持:
  
  為能正確地顯示多字節字符,瀏覽器及其所運行的操作系統應提供對特定語言的支持,比如字體和字碼表。
  
  瀏覽器編碼設置
  
  服務器返回的HTML頭(<meta http-equiv="content-type" content="text/html;charset=gb2312">)向瀏覽器聲明了該頁面使用的編碼方式,否則瀏覽器將使用默認編碼設置或自動進行匹配。當然,用戶也可以對頁面的編碼進行設定,如圖6所示。
  
 實現J2EE中的多字節字符處理(組圖)(圖六)
  圖6 Netscape的編碼設置頁

  
  因此假如頁面沒有聲明,多字節字符就可能顯示不正確,在這種情況下用戶必須手工設定當前頁面的編碼方式。
  
  HTTP POST編碼
  
  用HTML頁面的Form標簽向服務器提交數據會使情況變得更為復雜。瀏覽器的編碼方式取決于當前頁面的編碼設定,對Form標簽也照此處理。這意味著假如ASCII格式的HTML頁面用ISO-8859-1編碼,那么用戶在此頁面中將不能提交中文字符。這是因為所有提交的數據都用ISO-8859-1編碼,這將使中文字符丟失字節。所有的瀏覽器都遵守這個HTML標準。
  
  HTTP GET編碼
  
  URL鏈接中帶有多字節字符會使事情復雜化,像<A href = getuser.jsp?name=**>View detail information of this user</A>(**代表多字節字符)。這種情況很常見,例如在鏈接里加入用戶名或其它信息以便傳給下一頁。但RFC (因特網標準草案) 2396中并未明確規定URL中有非US-ASCII字符時的格式,不同的瀏覽器會采用它們自己的方式來編碼URL中的多字節字符。
  
  以Mozila為例(如圖7/8/9/10),通常是在HTTP請求發送前對URL編碼。我們知道在URL編碼過程中,首先根據某種編碼方式(如UTF-8或GBK)將一個多字節字符轉換成兩個或更多的字節,然后每個字節用3個字符組成的字符串%xy來表示,其中xy是表示該字節的兩個十六進制數。這方面的更多信息可參考HTML規范。不管怎樣,URL編碼所采用的編碼方式取決于當前頁面的編碼方式。
  
  我用下面這個gbk_test.jsp頁面做演示:
  清單3 gbk_test.jsp
  <%@page contentType="text/html;charset=GBK"%><HTML>
  <BODY>
  <a href='/chartest/servlet/httpGetTest?name=王'><h1>Test for GBK encoded URL</h1></a>  </BODY></HTML>
  
  x738b是一個中文字符的轉義值,這個中文字符就是我的姓。該頁面如圖7所示。
  
 實現J2EE中的多字節字符處理(組圖)(圖七)
  圖7 Mozilla的URL

  
  當鼠標移動到該鏈接上時,鏈接的地址就會在狀態欄中顯示出來,可以看到URL中嵌入了一個中文字符。點擊頁面中的鏈接,可以從地址欄中清楚地看到該字符已被URL編碼。字符x738b被編碼為%CD%F5,這是URL編碼與GBK編碼共同作用的結果。在服務器端,用request.getQueryString()方法取出查詢字符串;為與查詢字符串相比較,接下來的一行用另一種方法getParameter(String)來顯示字符,如圖8所示。
  
 實現J2EE中的多字節字符處理(組圖)(圖八)
  圖8 Mozilla中的URL編碼

  
  把當前頁面的編碼方式由GBK改為UTF-8,再次點擊頁面中的鏈接,出現的結果為:x738b被編碼為%E7%8E%8B,如圖9所示,這是URL編碼與UTF-8共同作用的結果。
  
 實現J2EE中的多字節字符處理(組圖)(圖九)
  圖9 Mozilla中的URL編碼

  
  Microsoft的IE瀏覽器卻以不同的方式處理多字節的URL編碼。IE在HTTP請求發送前不對URL編碼,URL編碼方式取決于當前頁面的編碼方式,如圖10所示。
  
 實現J2EE中的多字節字符處理(組圖)(圖十)
  圖10 IE不對URL編碼

  
  IE還有一個高級選項設置,可以強制瀏覽器總是以UTF-8編碼方式發送URL請求,如圖11所示。
  
 實現J2EE中的多字節字符處理(組圖)(圖十)
  圖11 IE中的高級選項設置

  
  根據以上說明我們會面臨一個問題:假如應用頁面的URL鏈接中帶有多字節字符,只要用GBK編碼就能在Mozilla里正常使用;但假如用戶的客戶端是IE,且在設置中強制瀏覽器以UTF-8編碼發送URL請求,那么在使用中就會碰到問題。
  
  多字節字符問題的解決方案
  
  編寫能運行于任何服務器、在任何瀏覽器中都能正常顯示的J2EE應用是個挑戰,下面是一些針對J2EE應用多字節字符問題的解決方案:
  
  通用原則:從不假定客戶端(瀏覽器)和服務器端有任何默認設置。
  
  &  在編輯階段,不要假定IDE的默認編碼設置是你想要的,要手工設置它們。
  
  假如IDE不支持特定語言,就在Java代碼中用/uXXXX轉義序列,在HTML頁面中用&#XXXX轉義序列,或用隨JDK分發的native2ascii工具將本地文字字符串轉換成Unicode轉義序列,這樣就能避免絕大部分問題。
  
  &    在編碼階段,從不假定服務器默認的編碼處理設置是正確的,而用下面的方法顯式指定:
  ·請求:setCharacterEncoding()
  ·響應:setContentType(), setLocale(), <%@ page contentType="text/html; charset=encoding" %>
  
  在為多種語言開發應用時,采用UTF-8編碼方式或將所有語言的字符都用/uXXXX轉義序列表示。
  
  · 在編譯Java類時,確保當前語言環境變量與編碼方式正確匹配。
  · 在配置階段,盡可能地使用標準設置。例如在Servlet 2.4規范中有一個配置每個應用的字符編碼方式的標準:
  
  <locale-encoding-mapping-list>
  <locale-encoding-mapping>
  <locale>ja</locale>
  <encoding>Shift_JIS</encoding>
  </locale-encoding-mapping>
  </locale-encoding-mapping-list>
  
  當與外部系統通信時,盡可能地找出這些系統的編碼方式,假如編碼不同就進行轉碼。可以用UnicodeFormatter.java作為調試器打印所有的字節:
  
  清單4 UnicodeFormatter.java
  import java.io.*;public class UnicodeFormatter {  static public String byteToHex(byte b) {
  // Returns hex String representation of byte b
  char hexDigit[] = {
  '0', '1', '2', '3', '4', '5', '6', '7',
  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'   };
  char[] array = { hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f] };
  return new String(array);
  }  static public String charToHex(char c) {
  // Returns hex String representation of char c
  byte hi = (byte) (c >>> 8);
  byte lo = (byte) (c & 0xff);
  return byteToHex(hi) + byteToHex(lo);
  }}
  
  總在HTML頁面中對編碼方式做顯式聲明,例如<meta http-equiv="content-type" content="text/html;charset=gb2312">,不要假定瀏覽器的默認設置是正確的。
  
  · 不要在鏈接里加入多字節字符,例如查詢字符串里不要用用戶名,改用用戶ID。
  · 假如必須在鏈接里加入多字節字符,那就要對URL進行手工編碼,可以在服務器端處理(用Java),也可以在客戶端處理(用javascript或VBscript)。
  
  難題之一:UTF-16
  
  有了前面的知識,現在我們來分析一個真正的難題,這是我負責的一個ISV(獨立軟件開發商)在項目中碰到的:J2EE中的UTF-16。
  
  現行的中文字符標準(GB18030)定義并支持27,484個中文字符。盡管這個數字看起來很大,實際上對中國人來說還不夠。目前中文擁有60,000多個字符,每年還在快速增長,這個狀況對中國政府在信息化方面的工作會產生嚴重影響。例如我姐姐的名在標準字符集中就沒有,因此銀行或郵電系統的計算機就打不出她的名。
  
  我的ISV希望能建立一套完整的、能讓所有人滿足的中文字符系統。它定義了自己的字碼表,有兩個現成的字符字碼表可供選擇:采用GB18030標準,可擴充到1600萬個字符;或采用Unicode 3.1標準,可支持1,112,064個字符。GB18030標準定義了編碼規則,也叫做GB18030,它用起來很簡便,目前已被JDK支持。然而假如采用Unicode 3.1標準,我們就可以從三種編碼方式中進行選擇:UTF-8、UTF-16或UTF-32。
  
  我的ISV希望用UTF-16編碼來處理它對中文字符的Unicode擴展。UTF-16編碼最主要的特點就是所有的ASCII字符都被編碼為16位的單元,這會在各個階段引發問題。在幾個服務器上做過測試后,ISV發現J2EE應用根本不支持UTF-16編碼。果真如此嗎?我們一起來分析開發的各個階段以找出問題所在。
  
  編輯階段
  
  假如在Java、JSP或HTML源文件中有多字節文字字符串,就需要用支持它們的IDE。我用的是NetBeans,只要將文本編碼屬性設置為UTF-16就能輕松支持UTF-16編碼。圖12所示的是一個用UTF-16編碼的JSP頁面,它里面只有一個靜態文字字符串“hello world!”。該頁面在Tomcat上運行,在Mozilla中顯示。
  
 實現J2EE中的多字節字符處理(組圖)(圖十二)
  圖12 Mozilla中用UTF-16編碼的頁面

  
  編譯階段
  
  由于在Java或JSP源文件中帶有用UTF-16編碼的字符,因此需要編譯器的支持。可以用javac -encoding UTF-16命令來編譯Java源文件,而在NetBeans里則可通過GUI方便地設置編譯器的屬性。通過一些簡單的代碼測試可以發現:假如servlet文件中的字符是用UTF-16編碼的,那么運行時就不會有問題。
  
  運行時動態編譯的JSP文件值得我們注重。幸運的是,大多數服務器可以對JSP頁面的編碼方式進行配置;而不幸的是,在Tomcat和Sun ONE應用服務器上做測試時,我發現用來將JSP文件轉換為servlet Java源文件的Jasper不能識別被UTF-16編碼過的JSP標簽(比如<%page..%>),所有這些標簽都被當作文字字符串處理了!我認為問題的根源可能在于Jasper(大多數應用服務器都用它做JSP編譯器),因為它以字節為單位來識別JSP的特定記號和標簽。
  
  瀏覽器測試
  
  現在我們看到由于識別被UTF-16編碼過的JSP標簽失敗,JSP不能支持UTF-16編碼的文字字符,而servlets卻沒有這個問題。
  
  且慢!為使測試更能說明問題,我們在測試代碼中加入POST功能,讓用戶通過HTML的Form標簽提交UTF-16編碼的字符。從本文的資源一節中下載下面的示例程序:servlet PostForm.java和servlet ByteTest.java。Servlet PostForm.java用來輸出一個用UTF-16編碼的頁面,它有一個用來向服務器提交數據的表單。在ByteTest.java里,由于不能確定服務器是否配置為UTF-16編碼方式,我沒有用request.getParameter()方法顯示瀏覽器提交的數據,而改用request.getInputStream()方法從請求中提取原始數據,然后打印從瀏覽器得到的每一個字節。
  
  清單5 PostForm.java
  public class PostForm extends HttpServlet {  ....
  protected void processRequest(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
  response.setContentType("text/html;charset=UTF-16");
  PrintWriter out = response.getWriter();
  out.println("<html><head>");
  out.println("<meta content="text/html; charset=UTF-16/" http-equiv="content-type/">");
  out.println("</head><body>");
  out.println("<form action=/"servlet/ByteTest/" method=/"POST/">");
  out.println("<input type=/"text/" name=/"name/"><input type=/"submit/">");
  out.println("</form></body></html>");
  out.close();
  }
  ....
  }
  
  清單6 ByteTest.java
  public class ByteTest extends HttpServlet {
  ...
  protected void processRequest(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
  ServletInputStream in = request.getInputStream();
  response.setContentType("text/html");
  PrintWriter out = response.getWriter();
  byte[] postdata = new byte[50];
  int size = in.read(postdata,0,50);
  in.close();
  out.println("<html>");
  out.println("<head>");
  out.println("<title>Servlet</title>");
  out.println("</head>");
  out.println("<body>");
  printBytes(out,postdata, size, "postdata");    out.println("</body>");
  out.println("</html>");
  out.close();
  }...}
  
  在運行過程中PostForm頁面顯然會用UTF-16編碼,而ByteTest的輸出結果又會是什么呢?
  
  ·IE:盡管頁面是用UTF-16編碼的,瀏覽器對所有輸入的字符都采用UTF-8編碼。
  
  ·Mozilla:無論在這個UTF-16編碼的頁面里輸入什么字符,只有“=”這個字符能顯示出來,這個運行結果顯然是錯誤的。
  
  結論
  
  J2EE應用只能在以下條件下使用UTF-16編碼:
  
  ·只用于servlet編程
  ·瀏覽器只限制于用IE
  ·雖然瀏覽器端的頁面用UTF-16編碼,在服務器端要用UTF-8解碼
  
  實際上,在J2EE應用中使用UTF-8編碼并不困難。在Unicode 3.1標準中,UTF-8編碼與UTF-16編碼能處理的字符數目是一樣的,只是在存儲和處理效率方面有差異。
  
  結束語
  
  由此可見,假如J2EE應用碰到了多字節字符問題,你一定要深入到開發生命周期的各個階段,檢查服務器和客戶端的配置情況,并借助調試工具,這樣才能找出問題的根源所在。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲人成网站色ww在线| 日韩性xxxx爱| 久久影视三级福利片| 日韩久久午夜影院| 日韩欧美中文字幕在线播放| 国产欧美一区二区三区四区| 91在线色戒在线| 国产精品夜间视频香蕉| 国产精品久久久久久久久久三级| 日韩成人av在线| 国产精品视频内| 久久久久亚洲精品国产| 欧美激情视频播放| 美女精品久久久| 欧美最猛性xxxx| 日韩av最新在线观看| 国产狼人综合免费视频| 在线一区二区日韩| 久久97久久97精品免视看| xxxxxxxxx欧美| 免费av一区二区| 97国产一区二区精品久久呦| 久久91亚洲精品中文字幕奶水| 欧美中文字幕视频在线观看| 亚洲人成亚洲人成在线观看| 精品成人av一区| 精品成人69xx.xyz| 9.1国产丝袜在线观看| 欧美亚洲第一区| 中文字幕无线精品亚洲乱码一区| 一区二区三区动漫| 深夜精品寂寞黄网站在线观看| 538国产精品视频一区二区| 久久久999精品| 亚洲小视频在线观看| 日韩av快播网址| 日韩成人免费视频| 成人激情视频在线播放| 成人网中文字幕| 亚洲天堂一区二区三区| 国内精品久久影院| 美乳少妇欧美精品| 国产精品久久久久久网站| 欧美中文字幕在线播放| 亚洲精品99久久久久| 欧美成人h版在线观看| 亚洲国产精品va在线观看黑人| 日韩精品视频免费专区在线播放| 最近2019年中文视频免费在线观看| 久久精品久久久久久国产 免费| 97久久超碰福利国产精品…| 在线日韩日本国产亚洲| 久久综合色88| 91中文字幕一区| 欧美性猛交xxxx黑人| 亚洲人av在线影院| 国色天香2019中文字幕在线观看| 日韩性xxxx爱| 久久久人成影片一区二区三区| 中文字幕亚洲无线码a| 欧美极品第一页| 久久精品国产亚洲精品| 国产精品免费一区二区三区都可以| 98精品在线视频| 秋霞成人午夜鲁丝一区二区三区| 亚洲a级在线观看| 亚洲欧美在线磁力| 国产精品久久久久99| 日韩av在线精品| 欧美日韩在线免费| 久久久精品一区| 亚洲风情亚aⅴ在线发布| 在线观看亚洲视频| 姬川优奈aav一区二区| 午夜精品三级视频福利| 亚洲一区二区久久久久久久| 亚洲欧洲在线看| 国产精品中文字幕在线观看| 亚洲免费一在线| 久久色免费在线视频| 亚洲天堂av电影| 日韩中文字幕免费视频| 亚洲伊人成综合成人网| 日韩午夜在线视频| 日韩中文有码在线视频| 97国产一区二区精品久久呦| 欧美成人精品一区| 欧美电影在线观看网站| 国产成人avxxxxx在线看| 国产精品免费一区二区三区都可以| 久久精品成人欧美大片古装| 亚洲精品第一页| 91人人爽人人爽人人精88v| 美女啪啪无遮挡免费久久网站| 欧美激情一区二区三区高清视频| 久久综合电影一区| 国产一区二区免费| 国产精品成人播放| 欧美日韩在线视频观看| 色偷偷91综合久久噜噜| 久久99久久99精品免观看粉嫩| 久久免费成人精品视频| 国产这里只有精品| 日韩av网站大全| 7m精品福利视频导航| 国产在线精品一区免费香蕉| 久久精品人人做人人爽| 国产精品吴梦梦| 国产一区二区成人| 国模精品视频一区二区| 亚洲第一福利视频| 国模私拍一区二区三区| 亚洲欧美另类在线观看| 久久久噜久噜久久综合| 日韩精品在线看| 精品无码久久久久久国产| 成人a免费视频| 欧美大片va欧美在线播放| 日韩69视频在线观看| 欧美色视频日本版| 91综合免费在线| 在线激情影院一区| 91国内揄拍国内精品对白| 欧美裸体视频网站| 亚洲国产成人在线视频| 色综合色综合久久综合频道88| 日韩av电影手机在线| 国产精品一区二区久久| 中文字幕亚洲天堂| 欧美日本国产在线| 国产亚洲视频在线观看| 在线视频日韩精品| 亚洲美女福利视频网站| 欧美精品情趣视频| 在线国产精品视频| 日韩精品高清在线观看| 欧美性猛交xxxx乱大交极品| 亚洲伦理中文字幕| 成人欧美在线视频| www欧美xxxx| 在线观看视频99| 美女精品视频一区| 久久久久久久999精品视频| 欧美电影免费观看电视剧大全| 日韩av在线免费观看| 亚洲色图综合久久| 国产精品视频大全| 国产精品扒开腿做爽爽爽男男| 久久久久久久一区二区三区| 一区二区国产精品视频| 欧美黑人巨大xxx极品| 国产精品久久久久久久电影| 国产精品亚洲自拍| 久久99国产精品久久久久久久久| 国产欧美在线观看| 色综合天天综合网国产成人网| 91久久国产婷婷一区二区| 久久人91精品久久久久久不卡| 亚洲奶大毛多的老太婆| 亚洲天堂色网站| 国产日韩欧美综合| 欧美在线精品免播放器视频| 欧美激情一二区| 亚洲激情 国产|