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

解答

正しくない。

  • Java9(JEP226)で変わったのはリソースバンドルの取り扱い(PropertyResourceBundle) であって プロパティファイル .properties 全般の話ではない。
  • プロパティファイル.propertiesの文字エンコーディングについての取り決めはない。それを取り扱うプログラム次第でありUTF-8を正しく認識してくれるとは限らない。
    • 標準 API で UTF-8として(読もうと思えば)読めるようになったのは 1.6 からであって 9 からではない。ちなみに 1.5 以前は ISO 8859-1 前提。

背景

私はうろ覚えで何となく、現在の Java では .properties ファイルを UTF-8 で書ける、ascii2nativeは過去の遺物になった、のだと思いこんでいました。
ところが Spring Boot の application.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 に指定されているエンコーディング以外のリソースも読めます。