Java應用開發中的字符集與字符編碼

事出有因

在向HttpURLConnection的輸出流寫入內容時,因沒有設置charset,致使接收方對數據的驗籤不一致。java

 

URL url = new URL(requestUrl); //打開鏈接
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection(); ...... ...... //獲取輸出流
out = new OutputStreamWriter(urlConn.getOutputStream()); //發送請求參數
out.write(concatKeyValue(params, false)); out.flush()

 

回過頭來看,問題看似挺容易解決,只需在獲取輸出流時,指定字符編碼集web

out = new OutputStreamWriter(urlConn.getOutputStream(), "utf-8");

 

但實則費了一番工夫。期間內心產生了過如下的問題:數據庫

一、String.getBytes(String charset)與String(Byte[] bytes, String charset)的使用。數組

二、什麼場合下會涉及的字符編碼的轉換呢?網絡

三、在不顯示指定charset時,java使用Charset.defaultCharset()來獲取默認字符編碼。Charset.defaultCharset()的值來自哪裏?eclipse

爲了在之後的開發中,快速解決字符集相關問題。在這裏對字符集作了一次比較系統的學習。jvm

 

字符集與字符編碼

字符是各類文字與符號的總稱,好比語言符號、圖形符號、標點。ide

字符集是字符的集合,每一個字符集包含的字符個數不一樣,常見的字符集有:unicode字符集、ISO 8859字符集、GB2312字符集、GB18030字符集、BIG5字符集等。函數

字符編碼是以二進制數字來對應字符集中的字符,使得計算機可以識別字符集中的字符。學習

各個國家在制定編碼標準的時候,一般是同時制定字符集與編碼規範。所以常見的字符集,如GB2312,除了表示「字符集」這一層含義外,也包含了編碼的含義。

Unicode字符集有多種編碼方式,如UTF-八、UTF-16等;ASCII只有一種;大多數MBCS(Multi-Byte Chactacter System,即多字節字符系統)(包括GB2312)也只有一種。

 

Java

Java中的字節碼文件始終以unicode編碼方式保存。Java運行時建立的字符串變量、常量等字符串均以unicode編碼存儲在內存中。

當涉及數據讀寫時,就會涉及字符的編碼轉換問題,例如從磁盤讀取文件時、向磁盤寫入文件時、接收網絡發送來的數據時等。

數據存儲到物理介質或經過物理介質傳輸時,都是以bit流的形態存在。而要傳輸正確的bit流,就須要聲明和設置恰當的字符編碼。

getBytes()與getBytes(charset)

當不指定字符集時,getBytes內部會獲取當前操做系統的默認字符集。

getBytes得到字符串的指定編碼規範對應的字節數組,此過程稱爲編碼。

//s的字符編碼方式爲unicode(utf-16), jvm的默認編碼規則
String s = "咱們"; //獲得s的gbk編碼, unicode(utf-16) --> gbk
byte[] bytes = s.getBytes("gbk");

String的構造函數String(byte[] bytes, String charset)

//解碼,gbk --> unicode(utf-16)
String p = new String(bytes, "gbk");

 

Charset.defaultCharset()

此方式用來獲取默認字符集,默認字符集在jvm啓動時已經根據系統環境確認,不能夠修改(或者說修改並不會生效)。當jvm的啓動時,也能夠經過參數-Dfile.encoding指定字符集,或經過環境變量修改默認字符集。

另外也請注意咱們運行main方法與web項目的不一樣,它們啓動了jvm的不一樣實例,因此默認字符集可能不一樣。因此若是在main方法中打印Charset.defaultCharset().name()的值 與實際運行web項目時輸入的值不一樣,也不要以爲奇怪。

 

但凡涉及中文(web開發、I/O、數據庫讀寫等),亂碼問題會與咱們不期而遇,因此理解字符集和字符編碼就頗有必要。

 

另外:

當咱們使用IDE(idea/eclipse)時,咱們能夠設置開發環境所使用字符集。請注意:IDE中設置的字符集只能表明IDE在存取源代碼文件時使用了何種字符集,而不是class文件使用了何種字符集。

 

 

好文推薦:《java中文亂碼解決之道(五)—–java是如何編碼解碼的》

相關文章
相關標籤/搜索