getBytes(charsetname)與String(bytes,charsetname)

其實這篇博文是由上一篇博文引起的,因爲上一篇提到了getBytes(charsetname)與String(bytes,charsetname)這兩個方法,一直對編碼解碼不是很清楚,這次花費心思下決心搞明白它,在網上各處查資料,現在把我的理解說出來,僅供大家參考

首先要說,java中String的數據是如何存儲的,查看源代碼就可以知道,String的數據是存儲在char[] value這樣一個成員變量中的,char類型的大小在java中是2個字節
我們還知道,現在普遍使用的unicode版本是UCS-2,就是使用2個字節表示一個字符的unicode版本,這就對上了,java使用的就是UCS-2標準,所以,String中的value中存儲的都是一個個數字

比如’你’的unicode編碼是4f60,看下面的測試代碼

char c = '你';
System.out.println(Integer.toHexString(c));
System.out.println(Integer.valueOf(c));
System.out.println(c);

結果是:
4f60
20320

所以呢,現在我們知道了String內部其實存儲的是未經任何編碼的unicode編碼,就是那個對應字符的編碼,然後再看我們這兩個方法:

getBytes(charsetname)
意思是根據這個編碼來獲取字節數組
這又是什麼意思呢?
就是說將內存中的unicode編碼轉換爲charsetname格式所對應的字節數組
比如’你’,轉換爲utf-8是三個字接,所以得到的字節數組就是三個字節的
即[e4 bd a0]

然後String(bytes,charsetname)呢

意思就是將bytes這個字節數組按照charsetname解釋,組裝爲一個String保存起來
例如上面那個字節數組[e4 bd a0],按照utf-8解釋的話,存儲起來就是”你”這個字符串,如果按照其他編碼解釋,則不會解釋爲”你”

說個其他的,爲什麼在servlet中處理參數一般都需要這麼一句了來控制編碼:

String str = new String(param.getBytes(“ISO-8859-1”),”UTF-8”);

其實這很好理解,瀏覽器傳過來的字節數據是UTF-8編碼的,然後web容器默認這個字節數據是ISO-8859-1編碼的,所以使用ISO-8859-1把這個字節數據轉換變成了String存儲起來,相當於是進行了下面這個操作:

String s = new String(UTF8Bytes,”ISO-8859-1”);

注意這個編碼是單字節的,也就是將每一個字節都轉換成了unicode編碼,幸好是這樣,使我們有機會將這個String再轉換成和原來一模一樣的字節數組,所以纔有了我們平時用的最多的那一句編碼處理的代碼

最後,想再說一下,對編碼這塊不瞭解的原因,是我們理解錯誤,我們必須知道的是:

java內部存儲字符串使用的unicode編碼
我們通常會聽到有人說:“我需要將String由ISO-8859-1轉換爲GBK編碼”,這又是怎麼回事呢?實際上,我們並不是要“將 一個由ISO-8859-1編碼的String轉換爲GBK編碼的String”,反覆說明的是,JAVA中的String都是unicode編碼的,所以不存在“ISO- 8859-1編碼的String”或“GBK編碼的String”這樣的說法。而需要轉換的唯一的原因是String進行了錯誤的編碼。我們經常會碰到由ISO-8859- 1轉換爲諸如GBK/UTF-8等等這樣的需求。所謂的轉換過程是:String –> byte[] –>String

上面這一小部分引用自另一片文章,在這裏我極力推薦大家去看一下,對這塊表達的十分清楚,戳這

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章