Edited at

Java9以降.propertiesファイルをUTF-8で書けるようになった、は正しい?


解答

正しくない。


  • Java9(JEP226)で変わったのはリソースバンドルの取り扱い(PropertyResourceBundle) であって プロパティファイル .properties 全般の話ではない。

  • プロパティファイル.propertiesの文字エンコーディングについての取り決めはない。それを取り扱うプログラム次第でありUTF-8を正しく認識してくれるとは限らない。


    • 標準APIで UTF-8として(読もうと思えば)読めるようになったのは 1.6 からであって 9 からではない。ちなみに1.5以前は ISO 8859-1 前提。




背景

私はうろ覚えで何となく、現在のJavaでは .properties ファイルを UTF-8 で書ける、ascii2nativeは過去の遺物になった、のだと思いこんでいました。

ところがあるメジャーなプログラムのプロパティファイル .propertiesUTF-8 で日本語を書いたところ文字化けしてしまい、あれ、もしかして自分の理解が間違っているのかと思い調べ直したのがこの記事です。

この勘違いはおそらく自分だけではないと考えています。

例えば "JEP226" で検索すると日本語非日本語ともに "JEP 226: UTF-8 Property Files" と紹介されている記事がヒットしますし(ちなみに少なくとも現在のオフィシャルなタイトルは "JEP 226: UTF-8 Property Resource Bundles"だと思うんだけど、これだけみんなProperty Files Property Files書いてるってことは途中で変わったの?)、 .properties ファイルを読み込むAPIは ResourceBundle.getBundleだ、的な説明が検索結果で上位に出たり、ということから想像できます。


説明

リソースバンドルを取得する際に用いるメソッドResourceBundle#getBundle では InputStream を引数に取る PropertyBundle コンストラクタが用いられますが、このときの InputStreamcharsetUTF-8 であるとみなすように バージョン9 から変更されています。

他方、 プロパティをInputStreamからロードするメソッド Properties#load(InputStream)InputStreamcharset は従来と変わらず ISO 8859-1 が前提です。

なおどちらにも InputStream型でなくReader型を引数に取るものが バージョン1.6 から用意されており、そちらを用いれば JDKに指定されているエンコーディング以外のリソースも読めます。