こんにちは。ハンドルネーム「Javaを復習する初心者」です。このサイトはプログラミング言語Javaの復習・学習をするブログです。プログラムの開発・実行はEclipseで行ってます。
スポンサーリンク
お知らせ
  • 参考文献のページ作りました。
  • Amazon.co.jpアソシエイトに参加していますが、参考文献の紹介はもしもアフィリエイトに統一しました。
  • 2016年10月9日からは投稿ペースを落とします。週1回くらいにする予定です。
スポンサーリンク

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

こんにちは。「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) + " ");
            }

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

文字: 2147483647
長さ: 10
バイト列: 32 31 34 37 34 38 33 36 34 37 
文字: 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を知らないと気づかないエラーだと思います。