java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

BOM付きUTF-8ファイルの1文字目

投稿日:

最終更新日:2016年08月21日

アイキャッチ

こんにちは。「Javaを復習する初心者」です。

今回はBOM付きUTF-8ファイルの読み取りについての注意を確認しました。

テキストファイルを編集するとき、テキストエディタMeryというソフトを使っているのですが、UTF-8でテキストファイルを保存する場合、UTF-8(BOM付き)とUTF-8(BOM無し)という種類が選べます。wikipediaで調べた結果、バイトオーダーマークというデータの有無のことのようです。UTF-8のバイトオーダーマークは「0xEF 0xBB 0xBF」だそうです。

BOM無しと有りで実験

ではBOM付きテキストファイルをJavaで読み込んだ場合、1文字目の扱いはどうなるのか、実験してみました。BOM無しと有りのテキストファイル2つを用意し、「2147483647 2 a b」という内容で保存しました。以下のようにString型変数targetに最初の文字を格納しました。

ソース抜粋

            String target = br.readLine().split(" ")[0];

以下のように文字の出力、長さとバイト列の出力をしました。

ソース抜粋

            System.out.println("文字: " + target);

            System.out.println("長さ: " + target.length());

            System.out.print("バイト列: ");
            for (byte b : target.getBytes()) {
                System.out.print(Integer.toHexString(b) + " ");
            }

結果は以下のようになりました。

BOM無し

文字: 2147483647
長さ: 10
バイト列: 32 31 34 37 34 38 33 36 34 37 

BOM有り

文字: 2147483647
長さ: 11
バイト列: ffffffef ffffffbb ffffffbf 32 31 34 37 34 38 33 36 34 37 

上記のように出力された文字に変化はありませんでした。長さはBOM有りだと1多く、バイト列は先頭にffffffef ffffffbb ffffffbfが付与されています。ちなみに2進数だと11111111111111111111111111101111 11111111111111111111111110111011 11111111111111111111111110111111です。「0xEF 0xBB 0xBF」と少し違いますが、エディタの問題でしょうか。あまり深く考えないことにします。

Integer#parseInt

次にInteger.parseIntを実行してみましたが、BOM付きの場合は以下のエラーが出ました。

エラー

Exception in thread "main" java.lang.NumberFormatException: For input string: "2147483647"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:580)
	at java.lang.Integer.parseInt(Integer.java:615)
	at practice.Hello20160821.test(Hello20160821.java:36)
	at practice.Hello20160821.main(Hello20160821.java:15)

BOMの部分が影響しているらしく、NumberFormatExceptionが発生しました。

それではnew BigInteger(target)ならば大丈夫なのではないだろうか、と思いましたが、以下のエラーが出ました。

エラー

Exception in thread "main" java.lang.NumberFormatException: For input string: "2"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:580)
	at java.math.BigInteger.<init>(BigInteger.java:461)
	at java.math.BigInteger.<init>(BigInteger.java:597)
	at practice.Hello20160821.test(Hello20160821.java:38)
	at practice.Hello20160821.main(Hello20160821.java:16)

NumberFormatExceptionが発生しました。なぜ「For input string」の対象が「2」なのか不明です。深く考えないことにしました。

どうやらBOM付きで1文字目の数字は変換できないようです。BOMを知らないと気づかないエラーだと思います。