メモの日々


2009年11月17日(火) [長年日記]

[java] ソースにエンコーディングが不正な文字が含まれている際のjavacの挙動

コメント内にエンコーディングが不正な文字が含まれているソースファイルをコンパイルする必要があった。

Antを使うと

警告:この文字は、エンコーディング UTF-8 にマップできません。

という警告はでるがコンパイルできた。が、NetBeans 6.7.1でコンパイルすると

この文字は、エンコーディング UTF-8 にマップできません。

というエラー(警告じゃない)になりコンパイルできなかった。なんでや。

-sourceオプションの有無で動作が変わる

javacに渡されているオプションを比較したところ、「-source」オプションの有無によりjavacの挙動が変わることが分かった。次のようになる。

G:\home\kenichi\work\java>javac -version
javac 1.6.0_17

G:\home\kenichi\work\java>javac -encoding UTF-8 -source 1.6 B.java
B.java:1: この文字は、エンコーディング UTF-8 にマップできません。
//aaaaa?bbbbbb
       ^
エラー 1 個

G:\home\kenichi\work\java>javac -encoding UTF-8 -source 1.5 B.java
B.java:1: 警告:この文字は、エンコーディング UTF-8 にマップできません。
//aaaaa?bbbbbb
       ^
警告 1 個

G:\home\kenichi\work\java>javac -encoding UTF-8 B.java
B.java:1: 警告:この文字は、エンコーディング UTF-8 にマップできません。
//aaaaa?bbbbbb
       ^
警告 1 個

まとめると、

  • 「-source 1.6」を指定:エラー
  • 「-source 1.5」を指定:警告
  • 「-source」の指定なし:警告

ということ。NetBeansではプロジェクトのプロパティで「ソース/バイナリ形式」を「JDK 5」にすることで「-source 1.5」が付くようになるので、これで一応問題を回避できる。

Java 6でエンコーディングエラー時の仕様が変わっていた

javacの標準オプションの説明の -source の所に、

-source release
   受け付けるソースコードのバージョンを指定します。release には次の値
   を指定できます。

   1.3
       このコンパイラでは、JDK 1.3 以降に導入されたアサーション、総称、
       または他の言語機能をサポートしません。
   1.4
       JDK 1.4 で導入された、アサーションを含むコードを受け付けます。
   1.5
       JDK 5 で導入された総称および他の言語機能を含んだコードを受け付
       けます。
   5
       1.5 と同義です。
   1.6
       これがデフォルト値です。Java SE 6 では言語に対する変更は導入さ
       れませんでしたが、ソースファイル内のエンコーディングエラーが、
       以前のような「警告」ではなく、「エラー」として報告されるように
       なりました。
   6
       1.6 と同義です。

とあった。「1.6」の所の説明に注目。1.6でjavacの動作が変わっているのだ。

「これがデフォルト値です。」という言葉を信じれば、-sourceを指定しなかった場合と-source 1.6を指定した場合の動作は同じになるのが正しいはずだが、先に示した通りこのときの動作は違っている。javacのバグかなあ。

[vim] Vimでファイルを16進数ダンプ表示する

:%!xxd

を実行することで、開いているファイルを16進数ダンプ表示することができるのでメモ。ファイル全体をVimに付属の xxd コマンドで変換している。

この状態で編集もできるみたいだけれど試してないのでメモしない。

あと、文字の上で

ga

を実行することでその文字の文字コードが表示されることもメモ。

ヘルプのバイナリファイルの項(リンク切れ→http://vim-jp.org/vimdoc-ja/usr_23.html#23.4)に説明がある。Vim上で見るには「:help xxd」したときに表示されるユーザマニュアルへのリンクを辿ればよい。