new String(str.getBytes("iso8859-1"), "UTF-8");

1.編碼基礎知識   java

       最先的編碼是iso8859-1,和ascii編碼類似。但爲了方便表示各類各樣的語言,逐漸出現了不少標準編碼,重要的有以下幾個。  數組

1.1. iso8859-1 一般叫作Latin-1 瀏覽器

屬於單字節編碼,最多能表示的字符範圍是0-255,應用於英文系列。好比,字母a的編碼爲0x61=97。  網絡

    很明顯,iso8859-1編碼表示的字符範圍很窄,沒法表示中文字符。可是,因爲是單字節編碼,和計算機最基礎的表示單位一致,因此不少時候,仍舊使用iso8859-1編碼來表示。並且在不少協議上,默認使用該編碼。好比,雖然"中文"兩個字不存在iso8859-1編碼,以gb2312編碼爲例,應該是"d6d0 cec4"兩個字符(java字符佔2個字節),使用iso8859-1編碼的時候則將它拆開爲4個字節來表示:"d6 d0 ce c4"(事實上,在進行存儲的時候,也是以字節爲單位處理的)。而若是是UTF編碼,則是6個字節"e4 b8 ad e6 96 87"。很明顯,這種表示方法還須要以另外一種編碼爲基礎。  函數

2.2. GB2312/GBK  編碼

      這就是漢字的國標碼,專門用來表示漢字,是雙字節編碼,而英文字母和iso8859-1一致(兼容iso8859-1編碼)。其中gbk編碼可以用來同時表示繁體字和簡體字,而gb2312只能表示簡體字,gbk是兼容gb2312編碼的。  spa

1.3 unicode  code

      這是最統一的編碼,能夠用來表示全部語言的字符,並且是定長雙字節(也有四字節的)編碼,包括英文字母在內。因此能夠說它是不兼容iso8859-1編碼的,也不兼容任何編碼。不過,相對於iso8859-1編碼來講,uniocode編碼只是在前面增長了一個0字節,好比字母a爲"00 61"。  內存


      須要說明的是,定長編碼便於計算機處理(注意GB2312/GBK不是定長編碼),而unicode又能夠用來表示全部字符,因此在不少軟件內部是使用unicode編碼來處理的,好比java。  utf-8

1.4 UTF 

       考慮到unicode編碼不兼容iso8859-1編碼,並且容易佔用更多的空間:由於對於英文字母,unicode也須要兩個字節來表示。因此unicode不便於傳輸和存儲。所以而產生了utf編碼,utf編碼兼容iso8859-1編碼,同時也能夠用來表示全部語言的字符,不過,utf編碼是不定長編碼,每個字符的長度從1-6個字節不等。另外,utf編碼自帶簡單的校驗功能。通常來說,英文字母都是用一個字節表示,而漢字使用三個字節。 

      注意,雖說utf是爲了使用更少的空間而使用的,但那只是相對於unicode編碼來講,若是已經知道是漢字,則使用GB2312/GBK無疑是最節省的。不過另外一方面,值得說明的是,雖然utf編碼對漢字使用3個字節,但即便對於漢字網頁,utf編碼也會比unicode編碼節省,由於網頁中包含了不少的英文字符。 

2.Unicode、UTF-8 和 ISO8859-1到底有什麼區別

       將以"中文"兩個字爲例,經查表能夠知道其GB2312編碼是"d6d0 cec4",Unicode編碼爲"4e2d 6587",UTF編碼就是"e4b8ad e69687"。注意,這兩個字沒有iso8859-1編碼,但能夠用iso8859-1編碼來表示。 


3. java對字符的處理 

在java應用軟件中,會有多處涉及到字符集編碼,有些地方須要進行正確的設置,有些地方須要進行必定程度的處理。 

3.1 getBytes(charset) 

       這是java字符串處理的一個標準函數,其做用是將字符串所表示的字符按照charset編碼,並以字節方式表示。注意字符串在java內存中老是按unicode編碼存儲的。好比"中文",正常狀況下(即沒有錯誤的時候)存儲爲"4e2d 6587",若是charset爲"gbk",則被編碼爲"d6d0 cec4",而後返回字節"d6 d0 ce c4"。若是charset爲"utf8"則最後是"e4 b8 ad e6 96 87"。若是是"iso8859-1",則因爲沒法編碼,最後返回 "3f 3f"(兩個問號)。 

3.2 new String(charset) 

       這是java字符串處理的另外一個標準函數,和上一個函數的做用相反,將字節數組按照charset編碼進行組合識別,最後轉換爲unicode存儲。參考上述getBytes的例子,"gbk" 和"utf8"均可以得出正確的結果"4e2d 6587",但iso8859-1最後變成了"003f 003f"(兩個問號)。由於utf8能夠用來表示/編碼全部字符,因此new String( str.getBytes( "utf8" ), "utf8" ) === str,即徹底可逆。 

3.3 setCharacterEncoding() 

該函數用來設置http請求或者相應的編碼。 

       對於request,是指提交內容的編碼,指定後能夠經過getParameter()則直接得到正確的字符串,若是不指定,則默認使用iso8859-1編碼,須要進一步處理。

      參見下述"表單輸入"。值得注意的是在執行setCharacterEncoding()以前,不能執行任何getParameter()。java doc上說明:This method must be called prior to reading request parameters or reading input using getReader()。並且,該指定只對POST方法有效,對GET方法無效。分析緣由,POST方法在執行第一個getParameter()的時候,java將會按照編碼分析全部的提交內容,然後續的getParameter()再也不進行分析,因此setCharacterEncoding()無效。而對於GET方法提交表單是,提交的內容在URL中,一開始就已經按照編碼分析全部的提交內容,setCharacterEncoding()天然就無效。

       注意:iso-8859-1是JAVA網絡傳輸使用的標準字符集,而gb2312是標準中文字符集,當你做出提交表單等須要網絡傳輸的操做的時候,就須要把 iso-8859-1轉換爲gb2312字符集顯示,不然若是按瀏覽器的gb2312格式來解釋iso-8859-1字符集的話,因爲2者不兼容,因此會 是亂碼.

例子:

String str = "你好a";
// 編碼
byte[] gbk = str.getBytes("gbk");
byte[] utf = str.getBytes("utf-8");
System.out.println("gbk編碼:" + Arrays.toString(gbk));// gbk編碼:[-60, -29, -70, -61, 97]漢字在gbk中兩個字節
System.out.println("utf-8編碼:" + Arrays.toString(utf));// utf-8編碼:[-28, -67, -96, -27, -91, -67,97]漢字在utf-8中三個字節
byte[] iso = str.getBytes("ISO-8859-1");
System.out.println("ISO-8859-1編碼:" + Arrays.toString(iso));// ISO-8859-1編碼:[63, 63, 97]
// 解碼
String s1 = new String(utf, "utf-8");
String s2 = new String(utf, "gbk");
String s3 = new String(gbk, "utf-8");
String s4 = new String(gbk, "ISO-8859-1");(brower默承認能出現這樣的解碼,因此後面的編碼再解碼回去【後面的m,n】)
String s5 = new String(utf, "ISO-8859-1");
System.out.println("--------------------");
System.out.println("utf-8解碼:" + s1);// 你好a
System.out.println("gbk解碼:" + s2);// 浣犲a gbk用2個字節解碼,因此會多一個字符
System.out.println("gbk用utf-8解碼:" + s3);// ???a utf-8解碼須要6個字節
System.out.println("iso用ISO-8859-1解碼:" + s4);// ??a iso用ISO-8859-1解碼:
System.out.println("---------------------");
System.out.println("用utf-8編碼回去");
s3 = new String(s3.getBytes("utf-8"), "gbk"); // 錕斤拷錕絘 gbk用utf-8解碼後沒法編回去
System.out.println(s3);

/**
* 規律:

* utf-8編碼能夠用gbk和iso8859-1解碼後編回去

* gbk編碼後只能用iso8859-1解碼後編回去
*/

System.out.println("gbk編碼後只能用iso8859-1解碼後編回去");
String m = new String(s4.getBytes("ISO-8859-1"), "gbk");
System.out.println(m);
System.out.println("---------------------");
System.out.println("utf-8編碼能夠用gbk和iso8859-1解碼後編回去");
String n = new String(s5.getBytes("ISO-8859-1"), "utf-8");
System.out.println(n);

規律:

utf-8編碼能夠用gbk和iso8859-1解碼後編回去

gbk編碼後只能用iso8859-1解碼後編回去

在JSP頁面獲取表單的值時會出現亂碼,有兩種解決方法:

1.在調用getParameter以前經過request.setCharacterEncoding設置字符編碼

2.調用new String(str.getBytes("iso8859-1"), "UTF-8");編碼後解碼

相關文章
相關標籤/搜索