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

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

 

一、「我」講的其它機器聽不懂?git

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

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

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

    (2)使用了byte傳遞數據tomcat

     在使用MQ、原生Socket等場景下,有時要用byte傳遞數據。這時必定要對String的getBytes方法傳遞編碼參數,通常用"UTF-8",且接收方則用new String(bytes, "UTF-8")來構造字符串,否則也有亂碼風險!建議對須要用byte傳遞數據的場景,儘可能轉爲Base64編碼的方式進行傳遞,更方便去調試程序。框架

    (3)設置運行環境編碼編碼

     若是你的系統默認編碼未設置對,那麼默認的Java代碼運行環境也不對,因此一要在程序運行時對Java代碼運行環境進行設置。以Linux Shell爲例,在啓動應用的shell裏,增長spa

export LANG=en_US.UTF-8

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

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

    再修改tomcat默認編碼(ISO-8859-1)方法,修改tomcat根目錄的conf下的server.xml,Connector元素添加URIEncoding="UTF-8"屬性:

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />

    這能夠保證應用的Java代碼的默認運行是在UTF-8編碼基礎上的,若是須要通訊的系統全設置爲UTF-8,能夠避免諸多編碼轉換!

 

二、瀏覽器不認識「我」?

     通常來講,瀏覽與應用的交互就是GET、POST請求了,固然還有PUT、DELETE請求,不過舉一反三,不須要講太多。

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

 

三、猜一猜「我」說的是什麼?

     在讀寫含中文文本的文件時,有時候也會讀出亂碼來,緣由是由於程序的運行編碼永遠只有默認的一種的,那麼若是不帶編碼參數地去讀取文件,因爲文件編碼可能與程序編碼不一樣,最後讀出來的就是亂碼了。這個時候,就須要寫程序去「猜」文件的編碼了。

     如今有許多開源的識別編碼的類庫能夠直接使用,可是也並不全是ok的,常見的編碼能識別就好,像這些:UTF-八、GB23十二、GBK、GB18030、UTF-1六、US-ASCII、Big五、ISO-8859-1,遇到的機率很是大。我這裏推薦幾個:EncodingDetecotrjChardet

     在讀取到byte後,經過編碼識別再存爲相應的String,就能夠獲得正常的中文了。

 

四、據說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} 這些字節。

 

     以上這些點若是注意了,常見的中文編碼問題就解決了,若是還有新的坑,博主會在此更新哈。

     轉載請註明原址:http://www.cnblogs.com/lekko/p/4943581.html 

相關文章
相關標籤/搜索