BOM(Byte Order Mark,位元組順序標記)是位於 Unicode 編碼文件開頭的特殊標記,用於識別文件的編碼類型與位元組序(Big-endian 或 Little-endian)。雖然 UTF-8 不強制要求 BOM,但許多 Windows 工具(如記事本)儲存 UTF-8 時會自動插入 BOM(EF BB BF),這在程式處理時常造成不可見的干擾。
| BOM (十六進位) | 對應編碼 |
|---|---|
| EF BB BF | UTF-8 |
| FE FF | UTF-16 (Big-endian) |
| FF FE | UTF-16 (Little-endian) |
| 00 00 FE FF | UTF-32 (Big-endian) |
| FF FE 00 00 | UTF-32 (Little-endian) |
早期 JDK(1.5 及之前)無法自動處理帶 BOM 的 UTF-8 檔案,解析 XML 會拋出 Content is not allowed in prolog 異常。常見的手動處理方式是讀取後跳過前 3 個位元組:
String xmla = StringFileToolkit.file2String(new File("D:\\projects\\mailpost\\src\\a.xml"), "UTF-8");
byte[] b = xmla.getBytes("UTF-8");
// 跳過前 3 個位元組 (EF BB BF)
String xml = new String(b, 3, b.length - 3, "UTF-8");
Document doc1 = DocumentHelper.parseText(xml);
// 後續 DOM4J 解析...
手動處理易出錯且不支援多種編碼。社區已有成熟工具 UnicodeReader,可自動偵測並移除各類 BOM,回傳乾淨的字串:
專案網址:https://koti.mbnet.fi/akini/java/unicodereader/
使用方式簡單,只需以 UnicodeReader 取代 InputStreamReader 即可:
Reader reader = new UnicodeReader(new FileInputStream(file), "UTF-8");
// 直接讀取,BOM 已自動移除
InputStreamReader 已支援 UTF-8 BOM 自動處理,但舊版專案仍需注意。W3C 規定 XML 解析器判斷編碼優先順序:
encoding 屬性;因此,產出 XML 時建議「不含 BOM + 明確宣告 encoding」,可最大相容性。
UnicodeReader 或 Apache Commons IO BOMInputStream 統一處理。file -i 或自訂腳本),防止 BOM 混入。掌握 BOM 特性並採用正確工具,即可避免「不可見字元」帶來的難以除錯問題。