java普通的文件讀取方式對於bom是沒法正常識別的。html
使用普通的InputStreamReader,若是採用的編碼正確,那麼能夠得到正確的字符,但bom仍然附帶在結果中,很容易致使數據處理出錯。
另外,對於存在BOM頭的文件,沒法猜想它使用的編碼。
java
實現一種方式,可對BOM頭進行捕捉和過濾apache
1、 使用apache的工具類,以BOMStream爲例:api
BOMStream,api參考:http://commons.apache.org/io/apidocs/org/apache/commons/io/input/BOMInputStream.html函數
該類的構造方式: BOMInputStream bomIn = new BOMInputStream(in) //僅能檢測到UTF8的bom,且在流中exclude掉bom BOMInputStream bomIn = new BOMInputStream(in, include); //同上,且指定是否包含 也能夠指定檢測多種編碼的bom,但目前僅支持UTF-8/UTF-16LE/UTF-16BE三種,對於UTF32之類不支持。 BOMInputStream bomIn = new BOMInputStream(in, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE); 有用的方法: bomIn.hasBOM()、hasBOM(ByteOrderMask.**)可用於判斷當前流中是否檢測到了bom。
讀取文件示例:工具
FileInputStream fis = new FileInputStream(file); //可檢測多種類型,並剔除bom BOMInputStream bomIn = new BOMInputStream(in, false,ByteOrderMark.UTF-8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE); String charset = "utf-8"; //若檢測到bom,則使用bom對應的編碼 if(bomIn.hasBOM()){ charset = bomIn.bs.getBOMCharsetName(); } InputStreamReader reader = new InputStreamReader(bomIn, charset); ...
2、使用一個更強大點的工具類(能夠支持UTF-8/UTF-16LE/UTF-16BE/UTF-32LE/UTF-32BE):
編碼
參考地址:http://koti.mbnet.fi/akini/java/unicodereader/, 下載其中兩個文件:UnicodeStream和UnicodeReaderspa
以UnicodeReader爲例:.net
FileInputStream fis = new FileInputStream(file); UnicodeReader ur = new UnicodeReader(fis, "utf-8"); BufferedReader br = new BufferedReader(ur); ...
相較於Apache的工具類,這裏的UnicodeReader 支持更多的BOM編碼。code
源碼解讀:
UnicodeReader 經過PushbackInputStream+InputStreamReader實現BOM的自動檢測和過濾讀取;
當沒有檢測到BOM時,pushback流將回退,並採用構造函數傳入的編碼進行讀取。
不然使用BOM對應的編碼進行讀取。
相對來講,第二種方式更加輕量和強大;另外也更加透明,能夠隨便修改源碼來實現本身的需求。
原文地址:http://blog.csdn.net/littleatp2008/article/details/6943215