String.getBytes()方法中的中文編碼問題

String的getBytes()方法是獲得一個系統默認的編碼格式的字節數組
getBytes("utf-8")  獲得一個UTF-8格式的字節數組java

把String轉換成bytes,各類編碼轉換成的bytes不一樣,好比UTF-8每一個漢字轉成3bytes,而GBK轉成2bytes,因此要說明編碼方式,不然用缺省編碼。數組

都是將一個string類型的字符串轉換成byte類型而且存入一個byte數組中。
在java中的全部數據底層都是字節,字節數據能夠存入到byte數組。
存儲字符數據時(字符串就是字符數據),會先進行查表,而後將查詢的結果寫入設備,讀取時也是先查表,把查到的內容打印到顯示設備上
getBytes()是使用默認的字符集進行轉換,getBytes(「utf-8」)是使用UTF-8編碼表進行轉換。

在Java中,String的getBytes()方法是獲得一個操做系統默認的編碼格式的字節數組。這表示在不一樣的操做系統下,返回的東西不同!服務器

String.getBytes(String decode)方法會根據指定的decode編碼返回某字符串在該編碼下的byte數組表示,如:
byte[] b_gbk = "中".getBytes("GBK");
byte[] b_utf8 = "中".getBytes("UTF-8");
byte[] b_iso88591 = "中".getBytes("ISO8859-1");
將分別返回"中"這個漢字在GBK、UTF-8和ISO8859-1編碼下的byte數組表示,此時學習

b_gbk的長度爲2,測試

b_utf8的長度爲3,編碼

b_iso88591的長度爲1。spa

而與getBytes相對的,能夠經過new String(byte[], decode)的方式來還原這個"中"字,操作系統

這個new String(byte[], decode)實際是使用指定的編碼decode來將byte[]解析成字符串.
String s_gbk = new String(b_gbk,"GBK");
String s_utf8 = new String(b_utf8,"UTF-8");
String s_iso88591 = new String(b_iso88591,"ISO8859-1");
經過輸出s_gbk、s_utf8和s_iso88591,會發現s_gbk和s_utf8都是"中",而只有s_iso88591是一個不被識別的字符(能夠理解爲亂碼),爲何使用ISO8859-1編碼再組合以後,沒法還原"中"字?緣由很簡單,由於ISO8859-1編碼的編碼表根本就不包含漢字字符,固然也就沒法經過"中".getBytes("ISO8859-1");來獲得正確的"中"字在ISO8859-1中的編碼值了,因此,再經過new String()來還原就更是無從談起。
所以,經過String.getBytes(String decode)方法來獲得byte[]時,必定要肯定decode的編碼表中確實存在String表示的碼值,這樣獲得的byte[]數組才能正確被還原。.net

注意:debug

有時候,爲了讓中文字符適應某些特殊要求(如http header要求其內容必須爲iso8859-1編碼),可能會經過將中文字符按照字節方式來編碼的狀況,如:
String s_iso88591 = new String("中".getBytes("UTF-8"),"ISO8859-1"),這樣獲得的s_iso8859-1字符串實際是三個在ISO8859-1中的字符,在將這些字符傳遞到目的地後,目的地程序再經過相反的方式String s_utf8 = new String(s_iso88591.getBytes("ISO8859-1"),"UTF-8")來獲得正確的中文漢字"中",這樣就既保證了遵照協議規定、也支持中文。

 

 最近在學JSP,在學習處理get方式提交數據出現亂碼問題的時候,對其中的一個解決方法new String(s.getBytes("iso-8859-1"),"utf-8");產生了疑問,就是爲何要使用s.getBytes("iso-8859-1")?

  當時只這樣想的:客戶端向服務器發送一個請求,好比說是一個字符串"請求";以後服務器接收到這個請求,也就是這個字符串,但是這時因爲某種緣由出現了亂碼!這時爲了解決這個問題,使用new String(s.getBytes("iso-8859-1"),"utf-8");解決問題。看到這條語句,我感受想不通啊,字符使用iso-8859-1編碼取得字節序列,再由utf-8解碼取得字符串,獲得的仍是亂碼啊!怎麼會取得正確的字符呢!!!想不通啊!

  以後,經過查找資料,獲得了一點想法,代碼以下:

複製代碼
 1 public class ThinkIng {
 2     public static void main(String[] args) throws Exception {
 3         System.out.println("\t------JSP模擬------");
 4         System.out.println("客戶端,有一箇中文字符的請求(轉換成了字節序列發送),發送至服務器端");
 5         String request="請求";
 6         byte[] client=request.getBytes();//客戶端的請求的字節序列
 7         print(client);
 8         System.out.println();//分割用的
 9         System.out.println("有一中間件,將發送的字符序列一默認的編碼格式(iso-8859-1)進行解碼");
10         String sever=new String(client,"iso-8859-1");
11         System.out.println(sever);
12         System.out.println("程序猿發現,這邊有問題,中文有亂碼,前來解決!");
13         String debug=new String(sever.getBytes("iso-8859-1"),"gbk");//還原字節序列,使用「gbk」從新進行解碼!
14         System.out.println(debug);
15         System.out.println("問題解決!");
16     }
17     public static void print(byte[] b){//用於顯示字節序列的
18         for(byte b1:b){
19             System.out.print(Integer.toHexString(b1 & 0xff)+" ");
20         }
21     }
22 }
複製代碼

  先前沒有想通主要是本身沒注意到:

  1. 沒有着重的想爲何會在輸出時出現字符亂碼?
  2. 客戶端發送求時,字符轉換成字節序列時的編碼方式是什麼樣的?

  總的來講,亂碼是因爲編碼方式與解碼方式不一致致使的,這一句話沒有理解透!若是當時這樣想既然出現了亂碼,確定是那邊的編碼格式和解碼格式不一致,就行了!

  注:編碼:將字符串轉換成字節序列;解碼:將字節序列轉換成字符串

  感謝:http://liguocai2009.iteye.com/blog/1602256這篇文章給個人啓發!

 

 

[java]  view plain  copy
 
  1. package com.test.bs;  
  2.   
  3. /** 
  4.  *  
  5.  * 一、Unicode是一種編碼規範,是爲解決全球字符通用編碼而設計的,而rUTF-8,UTF-16等是這種規範的一種實現。 
  6.  
  7.    二、java內部採用Unicode編碼規範,也就是支持多語言的,具體採用的UTF-16編碼方式。 
  8.  
  9.    三、無論程序過程當中用到了gbk,iso8859-1等格式,在存儲與傳遞的過程當中實際傳遞的都是Unicode編碼的數據,要想接收到的值不出現亂碼,就要保證傳過去的時候用的是A編碼,接收的時候也用A編碼來轉換接收。 
  10.  
  11.    四、若是雙方的file.encoding確保都相同,那就省事了,都默認轉了,但每每在不一樣項目交互時不少時候是不一致的,這個時候是必需要進行編碼轉換的。 
  12.  
  13.    五、不管如論轉換,java程序的數據都是要先和Unicode作轉換,這樣也就是能處理多語言字符集的緣由了。底層保持了一致,只要在傳值和接值的時候也一致就確定不會出現亂碼了。 
  14.  * */  
  15. public class UnicodeTest1 {  
  16.   
  17.     public static void main(String args[]) throws Exception {  
  18.   
  19.         String str = "中文字符";  
  20.   
  21.         System.out.println("original string---" + str);// 會正常輸出原始串  
  22.   
  23.         /** 
  24.          *  
  25.          * str.getBytes();  若是括號中不寫charset,則採用的是Sytem.getProperty("file.encoding"),即當前文件的編碼方式, 
  26.          *  
  27.          * 不少人寫的是系統的默認編碼,經過代碼測試並不是如此,實際獲得的是文件的編碼方式* 
  28.          *  
  29.          * str.getBytes("charset");//指定charset,即將底層存儲的Unicode碼解析爲charset編碼格式的字節數組方式 
  30.          *  
  31.          * String new_str=new String(str.getBytes("utf-8"),"gbk")); 
  32.          *  
  33.          * //將已經解析出來的字節數據轉化爲gbk編碼格式的字符串,在內存中即爲gbk格式的字節數組轉爲Unicode去交互傳遞 
  34.          */  
  35.   
  36.         String new_str = new String(str.getBytes("utf-8"), "gbk");  
  37.   
  38.         /** 
  39.          *  
  40.          * 此時的輸出是亂碼,在UTF-8的file.encoding下輸出gbk格式的數據確定是亂碼,可是new_str的確是gbk編碼式的 
  41.          *  
  42.          * 此時的亂碼源於encoding不符,但gbk格式的new_str自己數據並無問題,經過下面的轉換也能夠看得出來 
  43.          */  
  44.   
  45.         System.out.println("new string----" + new_str);  
  46.   
  47.         String final_str = new String(new_str.getBytes("gbk"), "utf-8");// 此處的含意與最上邊的註釋是一致的參數含意  
  48.   
  49.         /** 
  50.          *  
  51.          *輸出是正常的,此時將gbk編碼格式的new_str字符串,用gbk這個charset去解析它,而後用utf-8再轉碼一次, 
  52.          *  
  53.          * 由於new_str確實是gbk格式的,才能通過utf-8編碼獲得正常的數據顯示。 
  54.          */  
  55.   
  56.         System.out.println("final string---" + final_str);  
  57.   
  58.     }  
  59.   
  60. }  


 

 

[java]  view plain  copy
 
    1. package com.test.bs;  
    2.   
    3. import java.io.UnsupportedEncodingException;  
    4.   
    5. public class UnicodeTest2 {  
    6.   
    7.     public static void main(String[] args) {  
    8.         String a = "哈哈";  
    9.         try {  
    10.             byte[] gb2312 = a.getBytes("GB2312");  
    11.             byte[] utf = a.getBytes("UTF-8");  
    12.             for (int i = 0; i < gb2312.length; i++) {  
    13.                 System.out.print(gb2312[i]);  
    14.             }  
    15.             System.out.println();  
    16.   
    17.             for (int i = 0; i < utf.length; i++) {  
    18.                 System.out.print(utf[i]);  
    19.             }  
    20.             System.out.println();  
    21.   
    22.             System.out.println(new String(gb2312));  
    23.             System.out.println(new String(utf));  
    24.             System.out.println(System.getProperty("file.encoding"));//當前文件的編碼方式  
    25.             System.out.println(new String(utf, "UTF-8"));  
    26.             System.out.println(new String(gb2312, "UTF-8"));  
    27.         } catch (UnsupportedEncodingException e) {  
    28.             e.printStackTrace();  
    29.         }  
    30.   
    31.     }  
    32. }  
相關文章
相關標籤/搜索