BOM付きのUTF-8テキストファイルをJavaで読む方法を検討してみました。
結論として、ApacheのBOMInputStreamが便利だと思いました。
UTF-8のBOM (バイトオーダーマーク) とは
BOM (Byte Order Mark 、バイトオーダーマーク / バイト順マーク) とは、Unicode、UTF-8で記述された文書の冒頭に記載される短い符号です。
使用されている文字符号化方式(文字エンコーディング)の種類や、そのバイト順(エンディアン)を指定するためのものです。
エンディアンについては以下をご覧ください。
・https://urashita.com/archives/12325
BOMは正しく扱わないと、場合によっては深い問題に結構ハマります。
・https://urashita.com/archives/819
害があると思われるBOMですが、メリットもあります。
例えば、BOMのメリットの1つとして、
ExcelでBOMなしのUTF-8のCSVファイルを読むと文字化けするのに対して
ExcelでBOM付きのUTF-8のCSVファイルを読むと文字化けしません。
EncodeとBOMの16進数表現
エンコードとBOMの16進数表現の関係は以下の通りです。
エンコーディング | 表示 (16進数) | 表示 (10進数) |
---|---|---|
UTF-8 | EF BB BF | 239 187 191 |
UTF-16 (BE) | FE FF | 254 255 |
UTF-16 (LE) | FF FE | 255 254 |
UTF-32 (BE) | 00 00 FE FF | 0 0 254 255 |
UTF-32 (LE) | FF FE 00 00 | 255 254 0 0 |
JavaでBOMを避けて読み込む
JavaではBOMを避けて、テキストファイルを読み込むことが出来ません。
明示的にコーディングで避ける必要があります。
例えば、以下のように読み込めばよいでしょう。
1 2 3 4 5 6 7 8 |
public static final String UTF8_BOM = "\uFEFF"; private static String removeUTF8BOM(String s) { if (s.startsWith(UTF8_BOM)) { s = s.substring(1); } return s; } |
エンコーディングとBOMの16進数表現を考えると、これでも完全ではありません。
BOM付きUTF-8をJavaで読むApacheのBOMInputStream
ApacheのBOMInputStreamをJavaでBOMを上手に扱える便利なライブラリです。
通常は、JavaのInputStreamの代わりにBOMInputStreamを使えばよいです。
1 2 3 4 |
BOMInputStream bomIn = new BOMInputStream(in); if (bomIn.hasBOM()) { // has a UTF-8 BOM } |
BOMInputStreamは、Apache Commons IO (commons-io-2.8.0.jar) をダウンロードして使います。
・https://commons.apache.org/proper/commons-io/download_io.cgi
BOMを自前で解釈しようとすると、汎用的に作ろうとするとかなり大変なので、通常はこのライブラリを使うとよいでしょう。
コメント