隨筆 - 312, 文章 - 14, 評(píng)論 - 1393, 引用 - 0
          數(shù)據(jù)加載中……

          Java編碼問(wèn)題解決方案大揭密

          本文為原創(chuàng),如需轉(zhuǎn)載,請(qǐng)注明作者和出處,謝謝!

          一、Java編碼是怎么回事?

          對(duì)于使用中文以及其他非拉丁語(yǔ)系語(yǔ)言的開(kāi)發(fā)人員來(lái)說(shuō),經(jīng)常會(huì)遇到字符集編碼問(wèn)題。對(duì)于Java語(yǔ)言來(lái)說(shuō),在其內(nèi)部使用的是UCS2編碼(2個(gè)字節(jié)的Unicode編碼)。這種編碼并不屬于某個(gè)語(yǔ)系的語(yǔ)言編碼,它實(shí)際上是一種編碼格式的世界語(yǔ)。在這個(gè)世界上所有可以在計(jì)算機(jī)中使用的語(yǔ)言都有對(duì)應(yīng)的UCS2編碼。

          正是因?yàn)?/span>Java采用了UCS2,因此,在Java中可以使用世界上任何國(guó)家的語(yǔ)言來(lái)為變量名、方法名、類起名,如下面代碼如下:


          class 中國(guó)
          {
              
          public String 雄起()
              {
                   
          return "中國(guó)雄起";
              }
          }

          中國(guó) 祖國(guó) 
          = new 中國(guó)();
          System.out.println(祖國(guó).雄起());

              哈哈,是不是有點(diǎn)象“中文編程”。實(shí)際上,也可以使用其他的語(yǔ)言來(lái)編程,如下面用韓文和日文來(lái)定義個(gè)類:

          class ???
          {
              
          public void スーパーマン() {  }
          }

              實(shí)際上,由于Java內(nèi)部使用的是UCS2編碼格式,因?yàn)椋?/span>Java并不關(guān)心所使用的是哪種語(yǔ)言,而只要這種語(yǔ)言在UCS2中有定義就可以。

              UCS2編碼中為不同國(guó)家的語(yǔ)言進(jìn)行了分頁(yè),這個(gè)分頁(yè)也叫“代碼頁(yè)”或“編碼頁(yè)”。中文根據(jù)包含中文字符的多少,分了很多代碼頁(yè),如cp935cp936等,然而,這些都是在UCS2中的代碼頁(yè)名,而對(duì)于操作系統(tǒng)來(lái)說(shuō),如微軟的windows,一開(kāi)始的中文編碼為GB2312,后來(lái)擴(kuò)展成了GBK。其實(shí)GBKcp936是完全等效的,用它們哪個(gè)都行。

          二、Java編碼轉(zhuǎn)換

             
          上面說(shuō)了這么多,在這一部分我們做一些編碼轉(zhuǎn)換,看看會(huì)發(fā)生什么事情。

              先定義一個(gè)字符串變量:

              String gbk = "
          中國(guó)"; // “中國(guó)”在Java內(nèi)部是以UCS2格式保存的

              用下面的語(yǔ)言輸出一定會(huì)輸出中文:

          System.out.println(gbk);

              實(shí)現(xiàn)上,當(dāng)我們從IDE輸入“中國(guó)”時(shí),用的是java源代碼文件保存的格式,一般是GBK,有時(shí)也可是utf-8,而在Java編譯程序時(shí),會(huì)不由分說(shuō)地將所有的編碼格式轉(zhuǎn)換成utf-8編碼,讀者可以用UltraEdit或其他的二進(jìn)制編輯器打開(kāi)上面的“中國(guó).class”,看看所生成的二進(jìn)制是否有utf-8的編碼(utf-8ucs2之間的轉(zhuǎn)換非常容易,因?yàn)?/span>utf-8ucs2之間是用公式進(jìn)行轉(zhuǎn)換的,而不是到代碼頁(yè)去查,這就相當(dāng)于將二進(jìn)制轉(zhuǎn)成16進(jìn)制一樣,4個(gè)字節(jié)一組)。如“中國(guó)”的utf-8編碼按著GBK解析就是“涓  浗”。如下圖所示。



          如果使用下面的語(yǔ)言可以獲得“中國(guó)”的utf-8字節(jié),結(jié)果是6(一個(gè)漢字由3個(gè)字節(jié)組成)

          System.out.println(gbk.getBytes("utf-8").length);

          下面的代碼將輸出“涓  浗”。

          System.out.println(new String(gbk.getBytes("utf-8"), "gbk"));   

          由于將“中國(guó)“的utf-8編碼格式按著gbk解析,所以會(huì)出現(xiàn)亂碼。

          如果要返回中文的UCS2編碼,可以使用下面的代碼:

          System.out.println(gbk.getBytes("unicode")[2]);

          System.out.println(gbk.getBytes("unicode")[3]);

          前兩個(gè)字節(jié)是標(biāo)識(shí)位,要從第3個(gè)字節(jié)開(kāi)始。還有就是其他的語(yǔ)言使用的編碼的字節(jié)順序可能不同,如在C#中可以使用下面的代碼獲得“中國(guó)“的UCS2編碼:

          String s = "
          ";

          MessageBox.Show(ASCIIEncoding.Unicode.GetBytes(s)[0].ToString());

          MessageBox.Show(ASCIIEncoding.Unicode.GetBytes(s)[1].ToString());

              使用上面的java代碼獲得的“中“的16進(jìn)制UCS2編碼為4E2D,而使用C#獲得的相應(yīng)的ucs2編碼為2D4E,這只是C#Java編碼內(nèi)部使用的問(wèn)題,并沒(méi)有什么關(guān)系。但在C#Java互操作時(shí)要注意這一點(diǎn)。

              如果使用下面的java編碼將獲得16進(jìn)制的“中”的GBK編碼:

          System.out.println(Integer.toHexString(0xff & xyz.getBytes("gbk")[0]));

          System.out.println(Integer.toHexString(0xff & xyz.getBytes("gbk")[1]));

          “中”的ucs2編碼為2D4EGBK編碼為D6D0

              讀者可訪問(wèn)如下的url自行查驗(yàn):

              http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT

              當(dāng)然,感興趣的讀者也可以試試其他語(yǔ)言的編碼,如“人類”的韓語(yǔ)是“???”,如下面的代碼將輸出“???”的cp949ucs2編碼,其中cp949是韓語(yǔ)的代碼頁(yè)。


          String korean = "???"// 共三個(gè)韓文字符,我們只測(cè)試第一個(gè)“?”

          System.out.println(Integer.toHexString(
          0xff & korean.getBytes("unicode")[2]));

          System.out.println(Integer.toHexString(
          0xff & korean.getBytes("unicode")[3]));

          System.out.println(Integer.toHexString(
          0xff & korean.getBytes("Cp949")[0]));

          System.out.println(Integer.toHexString(
          0xff & korean.getBytes("Cp949")[1]));

           

          上面代碼的輸出結(jié)果如下:

          c7

          78

          c0

          ce

              也就是說(shuō)“?”的ucs2編碼為C778cp949的編碼為C0CE,要注意的是,在cp949中,ucs2編碼也有C0CE,不要弄混了。讀者可以訪問(wèn)下面的url來(lái)驗(yàn)證:

          http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP949.TXT

          Java支持的編碼格式

          三、屬性文件

          Java中的屬性文件只支持iso-8859-1編碼格式,因此,要想在屬性文件中保存中文,就必須使用UCS2編碼格式("uxxxx),因此,出現(xiàn)了很多將這種編碼轉(zhuǎn)換成可視編碼和工具,如Eclipse中的一些屬性文件編輯插件。

          實(shí)際上,"uxxxx編碼格式在javaC#中都可以使用,如下面的語(yǔ)句所示:

          String name= ""u7528"u6237"u540d"u4e0d"u80fd"u4e3a"u7a7a" ;

          System.out.println(name);

              上面代碼將輸出“用戶名不能為空”的信息。將"uxxxx格式顯示成中文非常簡(jiǎn)單,那么如何將中文還原成"uxxxxx格式呢?下面的代碼完成了這個(gè)工作:


          String ss = "用戶名不能為空";
          byte[] uncode = ss.getBytes("Unicode");
          int x = 0xff;
          String result 
          ="";
          for(int i= 2; i < uncode.length; i++)
          {
              
          if(i % 2 == 0) result += "\\u";
              String abc 
          = Integer.toHexString(x & uncode[i]);            
              result 
          += abc.format("%2s", abc).replaceAll(" ""0");               
          }
          System.out.println(result);

           

              上面的代碼將輸出如下結(jié)果:


          \u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a

              好了,現(xiàn)在可以利用這個(gè)技術(shù)來(lái)實(shí)現(xiàn)一個(gè)屬性文件編輯器了。

          四、Web中的編碼問(wèn)題

              大家碰到最多的編碼問(wèn)題就是在Web應(yīng)用中。先讓我們看看下面的程序:

           

          <!--  main.jsp  -->

            
          <%@ page language="java"  pageEncoding="utf-8"%>

            
          <html>
                
          <head>

                
          </head>

                
          <body>
                    
          <form action="servlet/MyPost" method="post">
                        
          <input type="text" name="user" />
                        
          <p/>
                        
          <input type="submit"  value="提交"/>
                    
          </form>

                
          </body>
            
          </html>


              下面是個(gè)Servlet

            package servlet;

            import java.io.IOException;
            import java.io.PrintWriter;
            import javax.servlet.ServletException;
            import javax.servlet.http.HttpServlet;
            import javax.servlet.http.HttpServletRequest;
            import javax.servlet.http.HttpServletResponse;

            
          public class MyPost extends HttpServlet
            {

                
          public void doPost(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException
                {
                    String user 
          = request.getParameter("user");
                    System.
          out.println(user);
                }
            }


              如果中main.jsp中輸入中文后,向MyPost提交,在控制臺(tái)中會(huì)輸出“中å?½”,一看就是亂碼。如果將IE的當(dāng)前編碼設(shè)成其他的,如由utf-8改為gbk,仍然會(huì)出現(xiàn)亂碼,只是亂得不一樣而已。這是因?yàn)榭蛻舳颂峤粩?shù)據(jù)時(shí)是根據(jù)瀏覽器當(dāng)前的編碼格式來(lái)提交的,如瀏覽器當(dāng)前為gbk編碼,就以gbk編碼格式來(lái)提交。 這本身是不會(huì)出現(xiàn)亂碼的,問(wèn)題就出在Web服務(wù)器接收數(shù)據(jù)的時(shí)候,HttpServletRequest在將客戶端傳來(lái)的數(shù)據(jù)轉(zhuǎn)成ucs2上出了問(wèn)題。在默認(rèn)情況下,是按著iso-8859-1編碼格式來(lái)轉(zhuǎn)的,而這種編碼格式并不支持中文,所以也就無(wú)法正常顯示中文了,解決這個(gè)問(wèn)題的方法是用和客戶端瀏覽器當(dāng)前編碼格式一致的編碼來(lái)轉(zhuǎn)換,如果是utf-8,則在doPost方法中應(yīng)該用以下的語(yǔ)句來(lái)處理:

              request.setCharacterEncoding("utf-8");

              為了對(duì)每一個(gè)Servlet都起作用,可以將上面的語(yǔ)句加到filter里。

              另外,我們一般使用象MyEclipse一樣的IDE來(lái)編寫jsp文件,這樣的工具會(huì)根據(jù)pageEncoding屬性將jsp文件保存成相應(yīng)的編碼格式,但如果要使用象記事本一樣的簡(jiǎn)單的編輯器來(lái)編寫jsp文件,如果pageEncodingutf-8,而在默認(rèn)時(shí),記事本會(huì)將文件保存成iso-8859-1ascii)格式,但在myeclipse里,如果文件中有中文,它是不允許我們保存成不支持中文的編碼格式的,但記事本并不認(rèn)識(shí)jsp,因此,這時(shí)在ie中就無(wú)法正確顯示出中文了。除非用記事本將其保存在utf-8格式。如下圖:


           

           





          Android開(kāi)發(fā)完全講義(第2版)(本書版權(quán)已輸出到臺(tái)灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2008-07-19 13:45 銀河使者 閱讀(8243) 評(píng)論(16)  編輯  收藏 所屬分類: javaweb 原創(chuàng)

          評(píng)論

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          good
          2008-07-19 14:54 | Skywalker

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          厲害 收藏!
          2008-07-19 15:02 | BeanSoft

          # re: Java編碼問(wèn)題解決方案大揭密[未登錄](méi)  回復(fù)  更多評(píng)論   

          LZ研究的還不錯(cuò)。不過(guò)研究的還是不夠深入啊。
          說(shuō)說(shuō)Web中的情況:
          request.setCharacterEncoding("utf-8");這個(gè)方法對(duì)與Tomcat這樣的服務(wù)器,有些版本就是不起作用的啦。
          還有個(gè),就是你的jsp例子中的FORM提交,LZ不知道有沒(méi)有研究過(guò)JavaScript中的提交情況,其實(shí)你也可以在網(wǎng)頁(yè)中的charset不是UTF-8的情況下,將所有傳到服務(wù)器的內(nèi)容全部編碼成UTF-8的。這個(gè)需要用到JavaScript的encodeURIComponent方法,具體的用法可以GOOGLE一下。
          其實(shí)關(guān)于亂碼有更好的解決方法,給大家提個(gè)思路:
          在客戶端將所有的中文全部編碼成一種可反編碼的編碼,比如Unicode的碼,用一定的標(biāo)識(shí)符間隔區(qū)分,然后在服務(wù)器端將接收到的編碼過(guò)的內(nèi)容再反編碼成實(shí)際的內(nèi)容。這樣就可以忽略編碼的不同了……
          2008-07-19 16:36 | James

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          @James
          不好意思,我的程序都是在tomcat6里調(diào)試通過(guò)的,再說(shuō)這些都是servlet規(guī)范規(guī)定的,所有的web服務(wù)器必須遵循。如果某個(gè)web服務(wù)器不遵循,那么web程序也就無(wú)法在其上正常運(yùn)行了。

          web亂碼的問(wèn)題非常多
          2008-07-19 16:46 | 銀河使者

          # re: Java編碼問(wèn)題解決方案大揭密[未登錄](méi)  回復(fù)  更多評(píng)論   

          LZ可以試驗(yàn)一下Tomcat5,5當(dāng)中設(shè)置request.setCharacterEncoding("utf-8")就是沒(méi)有效果的。
          前段時(shí)間一直在搞編碼的統(tǒng)一問(wèn)題,測(cè)試過(guò)程中遇到的情況。這樣設(shè)置就沒(méi)有效果
          2008-07-19 16:50 | James

          # re: Java編碼問(wèn)題解決方案大揭密[未登錄](méi)  回復(fù)  更多評(píng)論   

          補(bǔ)充一個(gè),Servlet是規(guī)定了,不過(guò)有些服務(wù)器在實(shí)現(xiàn)這些Servlet的時(shí)候就不遵循啊,這讓開(kāi)發(fā)人員很是郁悶啊。
          比如,response.setCharacterEncoding(String charset);這個(gè)方法在有些版本的WebLogic服務(wù)器中就沒(méi)有實(shí)現(xiàn)它,結(jié)果導(dǎo)致你使用這個(gè)方法的話,在某版本的Weblogic服務(wù)器中就沒(méi)有效果,而且會(huì)拋Error
          2008-07-19 16:52 | James

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          @James

          我的程序是在tomcat6調(diào)試通過(guò)的,你說(shuō)的可能是tomcat5以前的版本,但那應(yīng)該是這些版本的bug,從理論上,是必須支持這個(gè)功能的,否則web程序是無(wú)法在這些web服務(wù)器上運(yùn)行的。但很遺憾,我沒(méi)有碰到過(guò)這些版本的tomcat。

          至于web亂碼問(wèn)題,我只是簡(jiǎn)單提了一下,本文的目的并不是解決web亂碼問(wèn)題。而是讓讀者了解java內(nèi)部編碼的問(wèn)題。如果了解了java編碼原理,你認(rèn)為web亂碼問(wèn)題,甚至其他的亂碼問(wèn)題還能算是問(wèn)題嗎?

          你說(shuō)的沒(méi)錯(cuò),用form提交是產(chǎn)生亂碼問(wèn)題的一種原因,而用httpxmlrequest提交也會(huì)產(chǎn)生亂碼。這種情況下最好使用encodeURI或encodeURIComponent將中文編成%xxxx的形式,然后在服務(wù)端使用java.net.URLDecoder.decode方法進(jìn)行解碼。

          象在struts里的actionform,都可能會(huì)產(chǎn)生亂碼問(wèn)題。

          還有就是在http請(qǐng)求頭或響應(yīng)頭中傳中文,也會(huì)出現(xiàn)亂碼問(wèn)題。這些只要了解了java的編碼體系,都可以迎刃而解。


          最后總結(jié)一下:

          一般編碼傳送可以采用兩種方式:
          1、直接編碼。就是采用utf-8、gbk等形式。這樣在服務(wù)端可以使用setCharacterEncoding指定相應(yīng)的編碼。
          2、使用url形式的編碼。如%xxxx
          如果使用<form>的話,會(huì)根據(jù)當(dāng)前瀏覽器的編碼確定發(fā)送的中文編碼。
          如果用javascript,會(huì)以u(píng)tf-8編碼發(fā)送。
          2008-07-19 16:59 | 銀河使者

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          如果response.setCharacterEncoding不好使,可以試試response.setContentType("text/html;charset=utf-8");

          如果都不好使,就想別的方法,方法還是有的呢,可以用%xxxx形式,或是看一下setCharacterEncoding是怎么弄的,自已處理一下。
          2008-07-19 17:05 | 銀河使者

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          沒(méi)有辦法,由于做服務(wù)器的大多都是老外,它們永遠(yuǎn)不會(huì)有編碼問(wèn)題的,所以估計(jì)request.setCharacterEncoding方法就成了可選實(shí)現(xiàn)的功能的,但我想國(guó)產(chǎn)的web服務(wù)器應(yīng)該都支持,如apusic 。
          2008-07-19 17:06 | 銀河使者

          # re: Java編碼問(wèn)題解決方案大揭密[未登錄](méi)  回復(fù)  更多評(píng)論   

          @銀河使者
          你總結(jié)的各種編碼的原理和過(guò)程很不錯(cuò),對(duì)Java的編碼也是研究頗多。
          只是你說(shuō)的解決方案不是一個(gè)通用的解決之道,要針對(duì)不同的情況來(lái)區(qū)別對(duì)待。
          下面是我針對(duì)你采用的兩種方式的一點(diǎn)提醒,希望對(duì)看到這篇文章的人有點(diǎn)用
          1、直接編碼。服務(wù)器端使用setCharacterEncoding指定相應(yīng)的編碼,注意服務(wù)器的版本,比如Tomcat5.0版本中就不支持這個(gè)方法,設(shè)置后會(huì)沒(méi)有任何效果,使用的時(shí)候注意測(cè)試一下。如果不行,解決方法之一是換高版本的Tomcat,第二是用編碼轉(zhuǎn)換,在Tomcat中的默認(rèn)流編碼是ISO-8859-1的,只用進(jìn)行一個(gè)轉(zhuǎn)碼操作也就可以了。例:String pipeStr = new String(rawStr.getBytes("ISO-8859-1"), "UTF-8");//UTF-8可以改成自己想要的編碼
          2、如果代碼中拼湊的URL用到中文字符的時(shí)候,可以考慮用一個(gè)encodeURI或encodeURIComponent,方便服務(wù)器端進(jìn)行統(tǒng)一的UTF-8解碼。如果JavaScript與服務(wù)器端進(jìn)行交互,需要對(duì)返回的數(shù)據(jù),比如JSON數(shù)據(jù)進(jìn)行處理的話,在服務(wù)器端需要對(duì)返回?cái)?shù)據(jù)做好編碼工作,比如是通過(guò)response寫出的,需要加response.setContentType("charset=XXX");來(lái)保證返回的數(shù)據(jù)的編碼,使得JavaScript能夠正常解析。另外,如果有JavaScript文件是通過(guò)服務(wù)器端的Servlet動(dòng)態(tài)生成再傳回客戶端的話,建議JavaScript的編碼應(yīng)于客戶端的頭中的編碼一致,不然會(huì)出現(xiàn)JavaScript文件中的內(nèi)容亂碼的現(xiàn)象,盡管JavaScript某些時(shí)候能正常使用,但是還是沒(méi)有亂碼的好啊。

          PS:銀河使者 對(duì)編碼研究的挺深,有機(jī)會(huì)可以交流心得……
          2008-07-19 17:24 | James

          # re: Java編碼問(wèn)題解決方案大揭密[未登錄](méi)  回復(fù)  更多評(píng)論   

          現(xiàn)在主流的服務(wù)器都是國(guó)外的,是苦了我們啊,沒(méi)辦法啊……
          國(guó)內(nèi)的服務(wù)器做的好的又有幾個(gè)呢?apusic還可以,可是畢竟力量還是不夠強(qiáng)大啊。
          大家也就是總結(jié)這些東西的使用經(jīng)驗(yàn)和注意點(diǎn)……
          2008-07-19 17:31 | James

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          @ James
          不錯(cuò),你的第一種方法是比我的通用,因?yàn)槟愕姆椒ㄊ峭ㄟ^(guò)String類進(jìn)行編碼轉(zhuǎn)換的,而我的是通過(guò)web服務(wù)器所提供的setCharacterEncoding方法實(shí)現(xiàn)編碼轉(zhuǎn)換的。由于String類是jdk的標(biāo)準(zhǔn)類,所以這種轉(zhuǎn)換方式和web服務(wù)器無(wú)關(guān),任何基于java的程序(包括桌面程序)都可以使用這種方式進(jìn)行轉(zhuǎn)換。
          而且將其以ISO-8859-1取出,實(shí)際上用iso-8859-1往外取字節(jié),就相當(dāng)于是不經(jīng)過(guò)轉(zhuǎn)換,直接取出來(lái)了,如將“中國(guó)"的utf-8編碼“0xe4, 0xb8, 0xad,0xe5,0x9b, 0xbd”直接用iso-8859-1保存在String中(注意,不是將其轉(zhuǎn)換成ucs2,而是直接用utf-8共6個(gè)字節(jié)將其保存在String中),代碼如下:


          byte[] utf8 = new byte[]{(byte)0xe4, (byte)0xb8, (byte)0xad,(byte) 0xe5, (byte)0x9b, (byte)0xbd};
          String zg = new String(utf8, "iso-8859-1");
          String sss = new String(zg.getBytes("iso-8859-1"), "utf-8"); // 不能用utf-8
          String zg1 = new String(sss.getBytes("utf-8"), "utf-8");
          System.out.println(sss);
          System.out.println(zg1);

          其中 String zg = new String(utf8, "iso-8859-1");的作用就是將“中國(guó)”的6個(gè)utf-8編碼直接保存在String中,在這種情況下,不能使用zg.getBytes("utf-8")獲得字節(jié),因?yàn)間etBytes方法功能是將String中的ucs2編碼(4個(gè)字節(jié))轉(zhuǎn)換成utf-8編碼的6個(gè)字節(jié),而現(xiàn)在String中是6個(gè)字節(jié)的utf-8,而不是4個(gè)字節(jié)的ucs2,如果這時(shí)再用utf-8的話,java就會(huì)將這6個(gè)字節(jié)的utf-8編碼當(dāng)成了3個(gè)ucs2編碼(2個(gè)字節(jié)為一個(gè)ucs2編碼),所以就會(huì)出現(xiàn)亂碼了。

          而用zg.getBytes("iso-8859-1")就是將這6個(gè)字節(jié)的utf-8編碼按原樣取出,然后用 new String(zg.getBytes("iso-8859-1"), "utf-8");將這6個(gè)字節(jié)按著utf-8格式轉(zhuǎn)換成了java內(nèi)部使用的ucs2編碼。(實(shí)際上utf-8編碼并沒(méi)有真正轉(zhuǎn)化為ucs2,因?yàn)檫@樣太占資源了,在程序中還可能有很多英文字符,因此,utf-8就直接放到那了,反正將它轉(zhuǎn)換成ucs也很容易)。

          而在sss中的編碼就已經(jīng)是utf-8(ucs2)了,因此,必須使用下面的代碼獲得字節(jié)數(shù)組:
          sss.getBytes("utf-8")
          2008-07-19 18:30 | 銀河使者

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          要注意的一點(diǎn)就是getBytes和String都具有編碼轉(zhuǎn)換功能。
          getBytes是將ucs2轉(zhuǎn)換成其他的編碼,而String是將其他的編碼轉(zhuǎn)換成ucs2編碼
          2008-07-19 18:41 | 銀河使者

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          如果直接用getBytes("unicode"),就直接把ucs2編碼得出來(lái)了。

          如果用下面的代碼:
          zg.getBytes("unicode");

          由于zg是以iso-8859-1保存的,因此,按著字節(jié)輸出,就會(huì)有下面的結(jié)果:

          0
          e4
          0
          b8
          0
          ad
          0
          e5
          0
          9b
          0
          bd

          這也說(shuō)明iso-8859-1的編碼轉(zhuǎn)換成ucs2后,第一個(gè)字節(jié)補(bǔ)0
          2008-07-19 18:42 | 銀河使者

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          我看到網(wǎng)上關(guān)于在servlet中向客戶端輸出中文字符時(shí)亂碼解決方案一般是通過(guò)如下的代碼解決:

          response.setCharacterEncoding("utf-8");

          response.setContentType("text/html;charset=utf-8");

          但關(guān)鍵是web服務(wù)器轉(zhuǎn)換字節(jié)時(shí)是否讀取了這個(gè)設(shè)置的字符集編碼呢?如果未讀取,等于沒(méi)設(shè)。所以最通用的方法是采用如同的代碼解決向客戶端中文亂碼的問(wèn)題:

          String ss = "中華人民共和國(guó)";

          String utf8 = new String(ss.getBytes("utf-8"), "iso-8859-1");
          response.setCharacterEncoding("iso-8859-1");
          response.getWriter().write(utf8);

          2008-07-19 19:13 | 銀河使者

          # re: Java編碼問(wèn)題解決方案大揭密  回復(fù)  更多評(píng)論   

          慢慢看 編碼這個(gè)問(wèn)題在中文特別嚴(yán)重
          2008-07-19 22:15 | 黑蝙蝠
          主站蜘蛛池模板: 安阳县| 台湾省| 微博| 吉木乃县| 晋中市| 南漳县| 百色市| 阳原县| 沙雅县| 昔阳县| 晋中市| 河北省| 银川市| 阿勒泰市| 环江| 武邑县| 玛曲县| 湛江市| 诸暨市| 繁峙县| 司法| 益阳市| 杭锦旗| 黔西县| 永定县| 台东县| 罗田县| 阿荣旗| 洛宁县| 外汇| 海宁市| 徐汇区| 阳东县| 晋宁县| 抚顺县| 新野县| 永宁县| 尉犁县| 措勤县| 汉中市| 阿图什市|