解決Java以UTF-8匯出的CSV檔案用Excel開啟亂碼
專案中匯出或下載的CSV檔案,預設開啟方式一般都是Excel。若檔案中有中文或者日文時,顯示內容就會亂碼,但是如果用檔案編輯器記事本之類的開啟顯示內容是正常的。首先解釋一下為什麼會有這種現象,之後給出解決辦法。
亂碼原因
亂碼的大多數原因是檔案編碼和工具開啟檔案使用的編碼不統一導致。Excel開啟的CSV檔案預設是ANSI編碼,如果CSV檔案的編碼方式為UTF-8、Unicode等編碼可能就會出現檔案亂碼的情況。另外記事本支援UTF-8編碼,所以用記事本開啟顯示正常。
解決辦法
既然Excel不能識別檔案是UTF-8編碼,那就新增標識告訴Excel用UTF-8開啟。需要新增的標識就是BOM標識,新增的原因之後會介紹。
import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.OutputStreamWriter; public class Utf8BomTest { public static void main(String[] args) { FileOutputStream fos = null; OutputStreamWriter osw = null; BufferedWriter bw = null; try { fos = new FileOutputStream("d:\\kou\\test.csv"); //追加BOM標識 fos.write(0xef); fos.write(0xbb); fos.write(0xbf); osw = new OutputStreamWriter(fos, "UTF-8"); bw = new BufferedWriter(osw); bw.write("1,測試1,測試2"); //關閉流 bw.flush(); osw.flush(); fos.flush(); bw.close(); osw.close(); fos.close(); }catch(Exception e) { e.printStackTrace(); } } }
追加BOM標識前
追加BOM標識後
擴充套件知識
以上介紹瞭解決亂碼的方法,為什麼加了BOM標識後就不會亂碼呢,感興趣的朋友可以接著往下看。
BOM中文名是位元組順序標記(英語:byte-order mark,BOM)是位於碼點U+FEFF
的Unicode字元的名稱。常被用來當做標示檔案是以UTF-8、UTF-16或UTF-32編碼的標記。Windows就是使用BOM來標記文字檔案的編碼方式的。
UTF-8不需要BOM來表明位元組順序,但可以用BOM來表明編碼方式。當文字程式讀取到以EF BB BF
開頭的位元組流時,就知道這是UTF-8編碼了。同理,若沒有BOM的場合,可能無法正確識別編碼,工具會使用預設的編碼,編碼不匹配則會導致亂碼
UTF-8檔案中包含BOM的壞處
1、對php的影響
php在設計時就沒有考慮BOM的問題,也就是說他不會忽略UTF-8編碼的檔案開頭的那三個EF BB BF字元,直接當做文字進行解析,導致解析錯誤。
2、在linux上執行SQL指令碼報錯
參考文章
1.Java UTF-8のテキストファイルをBOM付きで作成する
https://www.javalife.jp/2018/02/26/post-441/
2.位元組順序標記-維基百科
https://zh.wikipedia.org/wiki/%E4%BD%8D%E5%85%83%E7%B5%84%E9%A0%86%E5%BA%8F%E8%A8%98%E8%99%9F
3.UTF-8和BOM的一些說明
https://www.cnblogs.com/codingmengmeng/p/11028744.html