Java對UTF-8格式檔案的讀取、寫入及新增BOM頭處理 - 程式人生
文章推薦指數: 80 %
資料管理系統可以自動匯出編碼為UTF-8的csv格式檔案,然而,距離在Windows上直接用Excel開啟它卻還有一步之遙:亂碼。
當歡歡喜喜地直接開啟這個檔案時,發現 ...
程式人生>java教程>Java對UTF-8格式檔案的讀取、寫入及新增BOM頭處理
Java對UTF-8格式檔案的讀取、寫入及新增BOM頭處理
•java教程•發佈:2018-10-08
_(:з」∠)_連我自己都覺得這個標題略長了……
事情的起因是這樣的:
資料管理系統可以自動匯出編碼為UTF-8的csv格式檔案,然而,距離在Windows上直接用Excel開啟它卻還有一步之遙:亂碼。
當歡歡喜喜地直接開啟這個檔案時,發現其中的漢字部分幾乎都是???,這個對於含有漢字的檔案肯定是不可接受的。
查詢了一下之後發現,這是由於微軟會悄悄地在UTF-8編碼的檔案前面新增BOM頭,所謂BOM頭是在檔案最開頭的16進位制的0xEF0xBB0xBF這三位。
反過來看的話,也就是說,如果UTF-8編碼的檔案沒有BOM頭的話,Windows下的軟體就可能無法識別UTF-8格式,採用其他的讀取辦法,從而就造成了亂碼。
Excel就是其中一個。
在理解了原理之後,我馬上就著手開始做對檔案的轉碼。
想當然地,借用了相當流行(目前中文的技術部落格互相轉載過多,有時真是讓搜尋的人覺得有點沮喪)的16進位制和字串互轉的方法,讀取檔案則採用BufferedReader(FileReader)直接使用readLine()的方法。
總的來說,就是第一行轉16進位制->插入BOM頭->16進位制轉第一行->依次讀取餘行不做操作寫入檔案——完成啦!
……這麼想的我真是太天真了!
在完成了一段小程式碼,打成jar包並測試結果之後,發現一些漢字確實成功地轉碼了,而另外一部分則顯示得很微妙。
舉個例子來說,其中“家”顯示成了“宿”,“區”顯示成了“匿”。
在初次嘗試之後,推測還是編碼上有一些問題。
Javadoc上對於FileReader/FileWriter類的說明是,它們分別是InputStreamReader/OutputStreamReader的拓展類,它們會使用【預設的編碼】,如果需要指定編碼的種類的話,則需要使用InputStreamReader/OutputStreamReader。
沿著這個線索,我嘗試在NetBeans8.0和jar包在系統執行這兩種情況下,列印了FileReader/FileWriter的執行的編碼,結果編碼為:
(1)NetBeans UTF-8
(2)Windows GBK
結合stackflow上的解答,可以推斷出,FileReader/FileWriter讀取和寫入的編碼,是與執行平臺的預設編碼一致的。
[1]
參考了InputStreamReader/OutputStreamReader的說明,終於寫出了下列的程式碼(這邊只是給出了核心程式碼),解決了兩個問題:
(1)對檔案新增BOM頭
(2)讀取和寫入檔案時的編碼指定
try{
FileInputStreamfis=newFileInputStream("input.csv");
InputStreamReaderisr=newInputStreamReader(fis,"UTF-8");
BufferedReaderbr=newBufferedReader(isr);
FileOutputStreamfos=newFileOutputStream("output.csv");
fos.write(newbyte[]{(byte)0xEF,(byte)0xBB,(byte)0xBF});
OutputStreamWriterosw=newOutputStreamWriter(fos,"UTF-8");
BufferedWriterbw=newBufferedWriter(osw);
while((Stringline=br.readLine())!=null){
bw.write(line);
bw.newLine();
}
bw.close();
br.close();
}catch(IOExceptione){
System.out.println(e.toString());
}
這段程式碼做了這些事情:
第2~4行:
這3行以UTF-8的格式打開了input.csv這個檔案,並且最終建立了一個BufferedReader物件。
第6~9行:
這4行以UTF-8的格式打開了output.csv這個檔案,最終建立了一個BufferedWriter物件。
其中第7行的操作,正是對檔案寫入BOM頭的操作。
第10~13行:
這4行程式碼從input.csv檔案逐行讀取內容,輸出到了output.csv。
必須要說一下這邊讓人覺得貼心的一點,如果一個UTF-8格式的檔案,它已經存在一個BOM頭了,這個BOM頭也是不會被讀取的,只有後面的字元會被讀取到,實在是幫了大忙了。
第14~15行:
這兩行做了BufferedReader和BufferedWriter兩個物件的關閉。
如果不關閉的話,可能會出現緩衝區資料的丟失。
值得一提的是,按照Javadoc的說法,如果關閉了這兩個物件,那麼和物件相關的檔案流也會被釋放。
也就是說,一串關聯的檔案流的關閉只要做一次就可以了,只要關閉最末端的檔案流就可以了。
這邊說兩句閒話>w<
雖說不關閉會出現異常是一個問題,可是促使我關閉檔案流的主要原因,果然還是因為我入門的程式語言是C++。
在用C++寫一長篇複雜程式碼時,其中相對比較機械的垃圾回收就是我寫程式的一個治癒點。
Java剝奪了這種樂趣,為此我還失落了很久……
以上就是對這段小程式碼的詳細解釋。
從結論來說,如果在讀取或者寫入的檔案中,有英語字元以外的內容,那麼比較好的習慣,就是使用上邊的程式碼,預先指定好編碼的型別,而不是使用FileReader/FileWriter這兩個封裝了功能的類,否則就可能因為平臺預設編碼的不同造成亂碼。
參考資料:
[1] JavaFileReaderencodingissue http://stackoverflow.com/questions/696626/java-filereader-encoding-issue
[2]Javadoc http://docs.oracle.com/javase/7/docs/api/
JAVA使用for迴圈列印三角形
«上一篇
JAVA系統剪下板工具類下一篇»
相關推薦
windowscmd視窗,輸出UTF-8格式檔案,顯示亂碼
本文來自網路,參考文件見文件末尾
想在windowscmd視窗中檢視utf-8中文,需要先執行以下步驟
ch...
python讀取帶BOM的utf-8格式檔案
**
UTF有哪些分類?
**
UTF-8分為兩種,一種是不帶BOM的,一種是帶BOM的。
其中第一種不...
php如何建立utf-8格式檔案
一般php建立的檔案預設不是utf-8格式的,在網上搜羅的解決辦法如下:
即將256個亮度等級的灰度影象通過適當的閥值選取而獲得仍然可以反映影...
Java檔案讀取,寫入資料庫
/**
*檔案讀寫及資料入庫工具包
*/
packagecom.xxx.file;
importjava.io.B...
VB.NET開啟Excel檔案,讀取Excel內容,新增到DataGridView中並顯示
'Excel新增:工程->參照追加→COM→MicrosoftExcel*.*ObjectLibrary 'D...
Java中utf-8格式字符串的存儲方法。
字節turnbyte[]spa負數oid只有一個ret字符串截取知識點:可通過byte[]bytes=...
Java實現CSV格式檔案的讀寫(操作API)
首先引入maven
延伸文章資訊
- 1Java - 读取UTF-8-BOM文件,第一个字段值为Null - CSDN博客
2. 从xls中copy数据到phone.txt中,此时phone.txt默认格式为UTF-8-BOM。 3. 查看文本编码格式,用nodepad打开文件,Encoding 即可查看文本编码格式...
- 2How to add a UTF-8 BOM in Java? - Stack Overflow
As noted in section 23.8 of the Unicode 9 specification, the BOM for UTF-8 is EF BB BF . That seq...
- 3Java处理UTF-8文件的BOM头部 - CSDN博客
Java处理UTF-8文件的BOM头部BOM——Byte Order Mark,就是字节序标记。基本概念在UCS 编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE“的字符,它...
- 4[ Java 常見問題] Handle UTF8 file with BOM - 程式扎記
參考至 這裡. Preface : 編碼問題一直是編程人員處理上很頭痛的問題, 特別是在處理 BOM 的時候. 舉例來說, 考慮有一個UTF-8 編碼檔案內容如下:
- 5Java Convert a File's Character Encoding from UTF-8 to UFT ...
To add a utf-8 BOM to a file is just a matter of prepending these 3 bytes to the file: 0xEF 0xBB ...