java 的字符編碼問題
java 的字符編碼問題-2
2008-11-17 11:01:23| 分類: JSP,JAVA,C等相關 | 標簽: |字號大中小 訂閱
String str=”中”; |
① |
byte[] bytes = str.getBytes(); |
② |
bytes = str.getBytes(“ISO-8859-1”); |
③ |
語句①:將一個只含有一個字符“中”的字符串文字量賦給 String 類的一個對象 str,字符文字量“中”是按照操作系統默認編碼方式進行編碼,在中文 windows 系統中通常是“GBK”,“中”在GBK編碼中是0xD6D0,在將該字符賦給str時,Java會對該字符串進行編碼轉換,即將GBK編碼方式的“中”轉換成Unicode編碼方式的“中”,Unicode編碼方式“中”的編碼是0x4E2D,所以str在程序運行期間在內存中的二進制表示成16進制就是0x4E2D。
語句②:獲得str字符串的二進制形式。getBytes(String encoding)方法需要指定編碼方式,表示獲得該字符串在何種編碼方式中的二進制形式。此語句中沒有設置參數,表示采用操作系統默認的編碼方式,即此處獲得的bytes是“中”在GBK編碼中的二進制形式,即bytes[0]=0xD6, bytes[1]=0xD0。
語句③:該語句與語句②的區別就是指定了編碼方式,此處指定的是ISO-8859-1,即通常所說的Latin-1,該編碼采用8bit對字符編碼,所以編碼空間中只有256個字符。該編碼中只包含了基本的ASCII碼和一些擴展的其它西歐字符,所以該字符集中不可能包含中文的“中”字,也就是說Java虛擬機無法在ISO-8859-1編碼集中找到“中”字對應的編碼,針對這種情況,就只返回一個問號(?,0x3f)字符,所以此時bytes.length只有1,且bytes[0]=0x3f。
2.new String(byte[] bytes, String encoding)
getBytes()方法從字符串獲得二進制的字節數組。如果要從二進制的字節數組獲得字符串,則就需要使用new String(byte[] bytes, String encoding)方法,該方法按照encoding編碼方法對字節數組bytes中的二進制數組進行解析,生成一個新的字符串對象。
byte[] bytes = {(byte)0xD6, (byte)0xD0, (byte)0x31}; |
① |
String str = new String(bytes); |
② |
str = new String(bytes,”ISO-8859-1”); |
③ |
語句①:定義一個字節數組。
語句②:將該字節數組中的二進制數據按照默認的編碼方式(GBK)編碼成字符串,我們知道GBK中0xD6 0xD0表示“中”,0x31表示字符“1”(GBK兼容ASCII,但不兼容ISO-8859-1除ASCII之外的部分),所以str得到的值是“中1”。
語句③:該句用ISO-8859-1編碼方式對該字節數據進行編碼,由于在ISO-8859-1編碼方式中一個字節會被解析成一個字符,所以該字節數組會被解釋成包含三個字符的字符串,但由于在ISO-8859-1編碼方式中沒有對應0xD6和0xD0的字符,所以前兩個字符會產生兩個問號,由于0x31在ISO-8859-1編碼中對應字符“1”(ISO-8859-1也兼容ASCII),所以此語句得到str的值是“??1”。
3.setCharacterEncoding()
該函數用來設置http請求或者相應的編碼。
對于request,是指提交內容的編碼,指定后可以通過getParameter()直接獲得正確的字符串,如果不指定,則默認使用iso8859-1 編碼,需要進一步處理。值得注意的是在執行setCharacterEncoding()之前,不能執行任何 getParameter()。而且,該指定只對POST方法有效,對GET方法無效。分析原因,應該是在執行第一個getParameter()的時候,java將會按照編碼分析所有的提交內容,而后續的getParameter()不再進行分析,所以setCharacterEncoding()無效。而對于GET方法提交表單時,提交的內容在URL中,一開始就已經按照編碼分析所有的提交內容,setCharacterEncoding()自然就無效。
對于response,則是指定輸出內容的編碼,同時,該設置會傳遞給瀏覽器,告訴瀏覽器輸出內容所采用的編碼。
<%@page pageEncoding="xxx"%>,xxx可以為GB2312,GBK,UTF-8(和MySQL不同,MySQL是 UTF8)等等,其默認值為ISO-8859-1。保存文件時的編碼應該與xxx 一致。
使用 <%@ page language="java" contentType="text/html; charset=xxx"%> 設置頁面顯示編碼。字符集的默認值為ISO-8859-1。
3. 頁面輸入編碼
在設置頁面顯示編碼的同時,指定了頁面的輸入方式。如果沒有指定頁面編碼,則使用操作系統本身的默認編碼。
四、表單傳遞參數編碼
使用表單輸入數據時,處理過程如下:
User input *(gbk:d6d0 cec4)
browser *(gbk: d6d0 cec4)
web server iso8859-1(00d6 00d 000ce 00c4) class,需要在class中進行處理:getbytes("iso8859-1")為d6 d0 ce c4,new String("gbk")為d6d0 cec4,內存中以 unicode編碼則為4e2d 6587。
1.用戶輸入的編碼方式和頁面指定的編碼有關。
2.從 browser 到 web server,可以在表單中指定提交內容時使用的字符集,否則會使用頁面指定的編碼。而如果在url中直接用 ? 的方式輸入參數,則其編碼往往是操作系統本身的編碼,因為這時和頁面無關。
3. Web server接收到的是字節流,默認時(getParameter)會以 iso8859-1編碼處理之,結果是不正確的,所以需要進行處理。但如果預先設置了編碼(通過 request. setCharacterEncoding ()),則能夠直接獲取到正確的結果。