編碼和解碼的定義:
電腦只能處理0100110這樣的位元字,字元是日常生活中我們使用的符號,為了使電腦能夠儲存、傳輸和展示字元,我們需要把字元轉換為0100101這樣的二進位碼,這就是編碼。
相反,把0100110這樣的二進位碼轉換為字元的過程就是解碼。
至於把哪個字元對應表到哪個二進位串上,是由國家(國家標準)、國際組織(國際標準)等來決定的。
一般不用二進位串來表示字元的編碼(看和閱讀都很困難),而是用十六進位的串來表示某個字元的編碼。因此,字元<-->十六進位串,之間的映射的集合就是我們所說的字元集了。
我們經常見到的字元集有:Unicode,UTF-8,GBK,GB2312,GB18030,Big-5,ISO-8859-1(又叫Latin-1)
Unicode,UTF-8能夠支援目前世界上所有語言文字的字元
GB2312是舊的國家標準,不支援繁體漢字
GBK不是國家標準,但支援繁體漢字
GB18030是新的國家標準,也支援繁體漢字
Big-5,能支援繁體漢字
ISO-8859-1不支援漢字,英美等拉丁語系的國家常用這個編碼
中國兩個字,用不同的編碼方式進行編碼,得到的結果也不相同 :
Unicode - FE, FF, 4E, 2D, 56, FD
UTF-8 - E4, B8, AD, E5, 9B, BD
GB18030 - D6, D0, B9, FA
ISO-8859-1 - 3F, 3F
關於Unicode:
用Unicode編碼後的“中國”,其編碼的前面有FE,FF兩個額外的位元組,這兩個位元組稱為BOM(Byte Order Mark)。“中”這個漢字,它的Unicode編碼是4E,2D,那麼在傳輸的過程中,是把4E放在前面,還是把2D放在前面呢。這有BOM來決定,如果BOm是FEFF(稱為Big Endian),表示4E在前面,如果BOM是FFFE(稱為Little Endian),表示2D在前
也就是,如果你的檔案編碼是Unicode(也可以叫做UTF-16),那麼檔案開頭的位元組就是FEFF(以這種方式開頭的編碼叫UTF-16BE)或FEFF(以這種方式開頭的叫UTF-16LE)。UTF-16BE、UTF-16、Unicode是一樣的。
關於UTF-8:
UTF-8編碼的檔案,其檔案也有一段標識:EF BB BF
其他編碼:
其他編碼的檔案。其檔案頭沒有什麼標識,關於ISO-8859-1對於“中國”的編碼是3F,3F,兩個相同,是應為它的字元集中根本就沒有“中國”這兩個字,所以用3F代替。
Java中的編碼和解碼問題:
JAVA可以把字元儲存在記憶體中(即也是以01101110的形式儲存在記憶體中)。Java在記憶體中儲存的編碼格式是Unicode。不過Java的class檔案是以UTF-8的方式來編碼的。Java虛擬機器讀取class檔案後,通過UTF-8編碼把檔案讀入記憶體,再轉換為UTF-16編碼.因此,如果語句是new String(byte[], "GB18030"),就是把位元組流(以GB18030編碼的)轉換為Unicode編碼的位元組流存入記憶體中。
如果想把一個位元組流轉換為字元流,就需要知道該位元組流是以什麼方式來編碼的,然後根據他的編碼方式來解碼就可以了。 開源工具:chardet,可以用來猜測某一段位元組流是用什麼編碼的。
如果我們拿到的一個字串,輸出時發現是一串亂碼,那麼是否可以通過某種技術手段來解決這個亂碼問題呢。答案是:不一定。
因為,首先該字串一定是先根據某個字元集將一個位元組流進行解碼而得到的。那麼:
如果它是按照ISO-8859-1字元集對位元組流進行解碼而得到的字串,恭喜你,你可以通過某種手段,把手中的亂碼重新轉換為正確的字串。方法就是:先getBytes("ISO-8859-1 "),得到一個位元組流,再用new String(Byte[], "正確的字元集")轉換為正確的字串即可。
如果它不是按照ISO-8859-1 字元集來解碼的,那很大可能就不能再轉換為正確的字串了。
通過Get方法想後台遞交請求:
向伺服器遞交的請求中,字元也是需要編碼之後傳輸的。瀏覽器將自動對URL地址中的漢字進行編碼之後傳輸。如果你直接在URL地址中輸入漢字,瀏覽器會根據當前字元的預設字元集進行編碼(中文作業系統是GB2312)再傳輸到伺服器;如果是在某個頁面中點擊的附帶中文的串連,那麼瀏覽器會根據這個頁面所使用的字元集對漢字進行編碼之後,傳輸到伺服器。
為了避免每次的編碼麻煩,我們可以直接在Tomcat中修改他對URL編碼的預設解碼字元集。就是修改server.xml檔案中的下面的語句,加上URIEncoding="GB18030"的配置:
<Connector port="8080" protocol="HTTP/1.1"
connection Timeout="20000"
redirectPort="8443" URIEncoding="GB18030"/>
通過Post方法向後台遞交請求:
瀏覽器將按照表單所在頁面所使用的字元集對資料進行編碼之後傳輸。在Tomcat中配置URIEncoding只對Get請求有效;對於Post請求,則必須在調用request.getParameter("XXX")之前,調用request.setCharacterEncoding("GB18030");
reponse編碼:
在調用response.getWrite()之前,調用response.setCharacterEncoding("GB18030") ;或者在執行response.setContentType("text/html;charset=GB18030");