Java對UTF-8格式檔案的讀取、寫入及新增BOM頭處理 - 程式人生

文章推薦指數: 80 %
投票人數:10人

資料管理系統可以自動匯出編碼為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



請為這篇文章評分?