歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java中文字符處理的四大迷題

Java中文字符處理的四大迷題

日期:2017/3/1 9:14:31   编辑:Linux編程

雖然計算機對英文字符的支持非常不錯,我們也恨不得寫的程序只會處理英文的數據,但是昨為中國人,無可避免地要處理一些中文字符。當很簡單的一件事情,遇到了中文,一切就不同了!本文就會講述實際生產環境中遇到的四個中文迷題,歡迎大家參與補充!

1、“我”講的其它機器聽不懂?

當把一串中文字符,通過HTTP、TCP方式傳遞到另外一個系統時,會經常驚奇地發現,在發送前還是好好的,但是收到後卻全壞了!怎麼辦?下面提供幾種情況,對症下藥:

(1)發送時使用的GET請求

要特別注意傳遞參數時,不要直接使用中文(如?key=熱情),這基本就宣告了這個代碼在某個浏覽器、某個機器上,對方收到的東西就是亂碼了。必須要對傳遞的參數進行Url Encode,接受方再進行Url Decode,取出來的數據基本就是OK的了。注:某些Java框架(如Spring)的RestTemplate會自動對GET方式的調用參與進行Encode、Decode,你就可以不用再人工去做了。

(2)使用了byte傳遞數據

在使用MQ、原生Socket等場景下,有時要用byte傳遞數據。這時一定要對String的getBytes方法傳遞編碼參數,一般用"UTF-8",且接收方則用new String(bytes, "UTF-8")來構造字符串,不然也有亂碼風險!建議對需要用byte傳遞數據的場景,盡量轉為Base64編碼的方式進行傳遞,更方便去調試程序。

(3)設置運行環境編碼

如果你的系統默認編碼未設置對,那麼默認的Java代碼運行環境也不對,所以一要在程序運行時對Java代碼運行環境進行設置。以Linux Shell為例,在啟動應用的shell裡,增加

export LANG=en_US.UTF-8

這可以保證應用在調用系統命令行時,運行環境是以UTF-8編碼的。另外如果是Tomcat,那麼的腳本處也加上參數項:

-Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8 -Duser.language=en -Duser.country=US

這可以保證應用的Java代碼的默認運行是在UTF-8編碼基礎上的,如果需要通信的系統全設置為UTF-8,可以避免諸多編碼轉換!

2、浏覽器不認識“我”?

一般來說,浏覽與應用的交互就是GET、POST請求了,當然還有PUT、DELETE請求,不過觸類旁通,不需要講太多。

POST請求的中文數據,經常是可以正常在前後台傳遞的,但是GET請求就沒那麼幸運了,一定要記得進行URL Encode與Decode,養成好的編碼習慣,減少後續調試代碼的難度與時間。

3、猜一猜“我”說的是什麼?

在讀寫含中文文本的文件時,有時候也會讀出亂碼來,原因是因為程序的運行編碼永遠只有默認的一種的,那麼如果不帶編碼參數地去讀取文件,由於文件編碼可能與程序編碼不同,最後讀出來的就是亂碼了。這個時候,就需要寫程序去“猜”文件的編碼了。

現在有許多開源的識別編碼的類庫可以直接使用,但是也並不全是ok的,常見的編碼能識別就好,像這些:UTF-8、GB2312、GBK、GB18030、UTF-16、US-ASCII、Big5、ISO-8859-1,遇到的概率非常大。我這裡推薦幾個:EncodingDetecotr、jChardet。

在讀取到byte後,通過編碼識別再存為相應的String,就可以得到正常的中文了。

4、聽說UTF-8還有BOM?

BOM,在UCS編碼中有一個叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF,這就是所謂的BOM頭了,它的UTF-8編碼是EF BB BF。在Windows系統上,默認用記事本存儲為UTF-8格式,是有BOM的,但是Linux下卻是默認無BOM的。缺了BOM的文件,經常在Windows下就識別出現錯位、亂碼等問題。解決之道就是在讀取文件、byte的前幾個字節,如果無BOM就給它加上BOM。

 1     /**
 2      * 判斷文件是否有BOM
 3      * 
 4      * @return
 5      */
 6     public static boolean hasBom(File file) {
 7         FileInputStream input = null;
 8         try {
 9             input = new FileInputStream(file);
10             byte[] buf = new byte[1024];
11             if ((input.read(buf, 0, 1024)) != -1) {
12                 if (buf[0] == (byte) 0xEF && buf[1] == (byte) 0xBB && buf[2] == (byte) 0xBF) {
13                     return true;
14                 }
15             }
16             return false;
17         } catch (IOException e) {
18             _logger.error(e);
19             return true;
20         } finally {
21             if (input != null) {
22                 try {
23                     input.close();
24                 } catch (IOException e) {
25                     _logger.error("資源釋放失敗!", e);
26                 }
27             }
28         }
29     }

如果無BOM,則在傳給Windows的地方或需要導出的地方這前先加上:new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF} 這些字節。

以上這些點如果注意了,常見的中文編碼問題就解決了。

Copyright © Linux教程網 All Rights Reserved