在java中讀取字符串時,不可避免的遇到處理漢字的問題,而漢字亂碼也是我們最常遇到的問題。
一、首先,我們先分析下java中字符串的存儲規則。
與其它語言一樣,java中的String實際上是一個char數組,在java中,一個char占16位也就是2個字節。所以可以表示0-65535種不同數據。
在java中,字符的顯示是通過一個叫字符集的東西的,簡單來說,就是一個序列(可能是一個,也可能是多個)的字節惟一地對應某個特定的符號(如漢字等)。
例如:GBK字符集中,兩個相臨字節:184 181表示人。97字節表示字符a;而在UTF-8編碼中,156 198 198三個相臨字節表示人字。一個字節97即表示a;
在java中,我們默認使用的字符集是GBK,當然,你也可以通過自己動手來改變使用的字符集,方法有以下三種:(以改變成"x-MacThai"字符集為例)
(1).Properties pps=System. getProperties();
pps.put("file.encoding","x-MacThai");
//設置完成後要將屬性保存
System.setProperties(pps);
(2).System.setProperty("file.encoding","x-MacThai");
(3).運行時設置 java -D file.encoding=x-MacThai
二、其次,我們來討論下我們出現漢字亂碼問題的原因。
我們先來分析下我們在傳輸、或者在文件讀寫時的操作,我們常使用的是out.write(string.getBytes())的方法來講我們需要的字符數據行輸出。在默認情況下,getBytes方法是對字符串按照GBK格式進行解析的,即:一個字符串str=”a人”那麼它解析後即變為”97 184 181”。
再來看看我們讀入數據的操作,如果我們使用了讀取整個比特流放入一個比特數組中,再將它以GBK的格式轉化為字符串的話自然沒有問題,可是如果我們如果使用了每讀到一個字節就將它轉化為一個字符加入字符串的話那麼將必然會出問題,就以上面的str=”a人”為例,它輸出的比特流為:97 184 181 而當你讀到97時將它轉為字符’a’後加到字符串中,這當然沒問題,可是再往後看,讀到184,程序還是會直接將它轉為對應的字符,那麼自然,問題就出來了,它只能對應出”?”,同樣,字符181也只能對應出”?”,因而讀到的字符串就變為也”a??”,這自然不是我們想要的結果。
三、最後,讓我們討論來如何解決問題吧,自然可以看出,是由於我們在讀取數據字符流時轉換到字符時出了問題,就是在轉換漢字時,本應是由兩個字符轉成一個漢字的我們卻對這兩個字符分別做了處理。
下面我們來寫一個算法來實現這個問題的解決吧!(以GBK為例)
(1)輸出流部分:
str=”a人”
在這裡,我們只需要將數據流按一定的字符集輸出即可。
out.write(str.getBytes(“GBK”));
注:java中默認的是GBK字符集,所以這裡不寫也沒關系。
(2)讀取數據部分:
查詢GBK字符集的規則可知道,為了區分漢字與英文字符,GBK中若讀到的一個字節為<128,那麼它表示一個英文字符或是符號,反之則為一個漢字。 知道規則後,我們便很好來設計算法了。
1> 讀取一個字節數據。
2> 若它小於128,則直接將其以GBK字符集轉為字符,加入到輸出字符串中。 轉第一步。
3> 若它大於等於128再讀取一個字節數據,將它們一起以GBK字符集轉為字符,加入到輸出字符串中。轉第一步。
四、小結:關於漢字,有許多的字符集可供使用。