小師妹學JavaIO之:文件編碼和字符集Unicode

[toc]java

小師妹學JavaIO之:文件編碼和字符集Unicodegit

簡介

小師妹一時興起,使用了一項歷來都沒用過的新技能,沒想卻出現了一個沒法解決的問題。把大象裝進冰箱到底有幾步?亂碼的問題又是怎麼解決的?快來跟F師兄一塊兒看看吧。程序員

更多精彩內容且看:github

使用Properties讀取文件

這天,小師妹心情很愉悅,吹着口哨唱着歌,標準的45度俯視讓人好不自在。編程

小師妹呀,什麼事情這麼高興,說出來讓師兄也沾點喜慶?架構

小師妹:F師兄,最新我發現了一種新型的讀取文件的方法,很好用的,就跟map同樣:編程語言

public void usePropertiesFile() throws IOException {
        Properties configProp = new Properties();
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("www.flydean.com.properties");
        configProp.load(in);
        log.info(configProp.getProperty("name"));
        configProp.setProperty("name", "www.flydean.com");
        log.info(configProp.getProperty("name"));
    }

F師兄你看,我使用了Properties來讀取文件,文件裏面的內容是key=value形式的,在作配置文件使用的時候很是恰當。我是從Spring項目中的properties配置文件中獲得的靈感,才發現原來java還有一個專門讀取屬性文件的類Properties。工具

小師妹如今都會搶答了,果真青出於藍。區塊鏈

亂碼初現

小師妹你作得很是好,就這樣舉一反三,很快java就要盡歸你手了,後面的什麼scala,go,JS等估計也通通不在話下。再過幾年你就能夠升任架構師,公司技術在你的帶領之下必定會蒸蒸日上。測試

作爲師兄,最大的責任就是給小師妹以鼓勵和信心,給她描繪美好的將來,什麼出任CEO,贏取高富帥等全都不在話下。據說有個專業的詞彙來描述這個過程叫作:畫餅。

小師妹有點心虛:但是F師兄,我還有點小小的問題沒有解決,有點中文的小小亂碼....

我深有體會的點點頭:馬賽克是阻礙人類進步的絆腳石...哦,不是馬賽克,是文件亂碼,要想弄清楚這個問題,還要從那個字符集和文件編碼講起。

字符集和文件編碼

在好久好久之前,師兄我都尚未出生的時候,西方世界出現了一種叫作計算機的高科技產品。

初代計算機只能作些簡單的算數運算,還要使用人工打孔的程序才能運行,不過隨着時間的推移,計算機的體積愈來愈小,計算能力愈來愈強,打孔已經不存在了,編程了人工編寫的計算機語言。

一切都在變化,惟有一件事情沒有變化。這件事件就是計算機和編程語言只流傳在西方。而西方平常交流使用26個字母加有限的標點符號就夠了。

最初的計算機存儲能夠是很是昂貴的,咱們用一個字節也就是8bit來存儲全部可以用到的字符,除了最開始的1bit不用之外,總共有128中選擇,裝26個小寫+26個大寫字母和其餘的一些標點符號之類的徹底夠用了。

這就是最初的ASCII編碼,也叫作美國信息交換標準代碼(American Standard Code for Information Interchange)。

後面計算機傳到了全球,人們才發現好像以前的ASCII編碼不夠用了,好比中文中經常使用的漢字就有4千多個,怎麼辦呢?

不要緊,將ASCII編碼本地化,叫作ANSI編碼。1個字節不夠用就用2個字節嘛,路是人走出來的,編碼也是爲人來服務的。因而產生了各類如GB2312, BIG5, JIS等各自的編碼標準。這些編碼雖然與ASCII編碼可是相互之間缺並不兼容。

這嚴重的影響了國際化的進程,這樣還怎麼去實現同一個地球,同一片家園的夢想?

因而國際組織出手了,制定了UNICODE字符集,爲全部語言的全部字符都定義了一個惟一的編碼,unicode的字符集是從U+0000到U+10FFFF這麼多個編碼。

小師妹:F師兄,那麼unicode和我平時據說的UTF-8,UTF-16,UTF-32有什麼關係呢?

我笑着問小師妹:小師妹,把大象裝進冰箱有幾步?

小師妹:F師兄,腦筋急轉彎的故事,已經不適合我了,大象裝進冰箱有三步,第一打開冰箱,第二把大象裝進去,第三關上冰箱,完事了。

小師妹呀,做爲一個有文化的中國人,要真正的承擔起民族復興,科技進步的大任,你的想法是很錯誤的,不能光想口號,要有實際的可操做性的方案才行,要否則咱們何時纔可以打造秦芯,唐芯和明芯呢?

師兄說的對,但是這跟unicode有什麼關係呢?

unicode字符集最後是要存儲到文件或者內存裏面的,那怎麼存呢?使用固定的1個字節,2個字節仍是用邊長的字節呢?根據編碼方式的不一樣,能夠分爲UTF-8,UTF-16,UTF-32等多種編碼方式。

其中UTF-8是一種變長的編碼方案,它使用1-6個字節來存儲。UTF-16使用2個或者4個字節來存儲,JDK9以後的String的底層編碼方式變成了兩種:LATIN1和UTF16。

而UTF-32是使用4個字節來存儲。這三種編碼方式中,只有UTF-8是兼容ASCII的,這也是爲何國際上UTF-8編碼方式比較通用的緣由(畢竟計算機技術都是西方人搞出來的)。

解決Properties中的亂碼

小師妹,要解決你Properties中的亂碼問題很簡單,Reader基本上都有一個Charsets的參數,經過這個參數能夠傳入要讀取的編碼方式,咱們把UTF-8傳進去就好了:

public void usePropertiesWithUTF8() throws IOException{
        Properties configProp = new Properties();
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("www.flydean.com.properties");
        InputStreamReader inputStreamReader= new InputStreamReader(in, StandardCharsets.UTF_8);
        configProp.load(inputStreamReader);
        log.info(configProp.getProperty("name"));
        configProp.setProperty("name", "www.flydean.com");
        log.info(configProp.getProperty("name"));
    }

上面的代碼中,咱們使用InputStreamReader封裝了InputStream,最終解決了中文亂碼的問題。

真.終極解決辦法

小師妹又有問題了:F師兄,這樣作是由於咱們知道文件的編碼方式是UTF-8,若是不知道該怎麼辦呢?是選UTF-8,UTF-16仍是UTF-32呢?

小師妹問的問題愈來愈刁鑽了,還好這個問題我也有準備。

接下來介紹咱們的終極解決辦法,咱們將各類編碼的字符最後都轉換成unicode字符集存到properties文件中,再讀取的時候是否是就沒有編碼的問題了?

轉換須要用到JDK自帶的工具:

native2ascii -encoding utf-8 file/src/main/resources/www.flydean.com.properties.utf8 file/src/main/resources/www.flydean.com.properties.cn

上面的命令將utf-8的編碼轉成了unicode。

轉換前:

site=www.flydean.com
name=程序那些事

轉換後:

site=www.flydean.com
name=\u7a0b\u5e8f\u90a3\u4e9b\u4e8b

再運行下測試代碼:

public void usePropertiesFileWithTransfer() throws IOException {
        Properties configProp = new Properties();
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("www.flydean.com.properties.cn");
        configProp.load(in);
        log.info(configProp.getProperty("name"));
        configProp.setProperty("name", "www.flydean.com");
        log.info(configProp.getProperty("name"));
    }

輸出正確的結果。

若是要作國際化支持,也是這樣作的。

總結

千辛萬苦終於解決了小師妹的問題,F師兄要休息一下。

本文的例子https://github.com/ddean2009/learn-java-io-nio

本文做者:flydean程序那些事

本文連接:http://www.flydean.com/io-charsets-properties/

本文來源:flydean的博客

歡迎關注個人公衆號:程序那些事,更多精彩等着您!

相關文章
相關標籤/搜索