properties ファイルの値を動的に取得する方法

現在のプロジェクトではあまり一般的ではない、そして古い思想のフレームワーク (フレームワークと呼べるようなモノではなく、単に基盤といった感じ) を利用しているため、メッセージ出力部分が非常に貧相です。そこで Java の標準的なやり方でメッセージファイルを外出しにして、java.util.Properties クラスを利用して値を取得、表示するように実装しました。

このようなことは過去にも何度もやっているのですが、少しだけ悩んでしまいました。メッセージファイル (ここでは messages.properties) ファイルに次のような記述があった場合、{0} や {1} にどうやって任意の値を流し込んで、全体のメッセージを取得するか、ということです。

warn.1001 = 接続に失敗しました。
warn.1002 = このフィールドは {0}〜{1} の長さを持つ必要があります。

messages.properties 自体の読み込みは java.util.Properties クラスだけでできるのですが、フォーマットを加えるとなるとそうはいかないわけで、どうやるのかを忘れてしまいました。結果的には java.text.MessageFormat クラスを利用すれば解決です。

import java.io.InputStream;
import java.text.MessageFormat;
import java.util.Properties;

public class MessageTester {

    public void run() throws Exception {
        // message.properties ファイル
        final InputStream inputStream = this.getClass().getClassLoader()
                .getResourceAsStream("messages.properties");

        Properties props = new Properties();
        // ファイルをロードする
        props.load(inputStream);

        // シンプルなメッセージ出力
        System.out.println(props.getProperty("warn.1001"));

        // 引数を与えてフォーマットしてメッセージ出力
        System.out.println(MessageFormat.format(props.getProperty("warn.1002"),
                "8", "32"));
    }

    public static void main(String[] args) throws Exception {
        MessageTester tester = new MessageTester();
        tester.run();
    }

}

実行結果はこちら。

接続に失敗しました。
このフィールドは 8〜32 の長さを持つ必要があります。

単純なメッセージ出力は

System.out.println(props.getProperty("warn.1001"));

これで大丈夫です。次にフォーマットの場合。

System.out.println(MessageFormat.format(props.getProperty("warn.1002"), "8", "32"));

MessageFormat#format は第1引数にフォーマット対象となる文字列を、それ以降の引数で流し込む値を指定してやります。第2引数は可変長引数として定義されていますので、必要なだけ与えてやることができます。ここでは "8" が {0} に、"32" が {1} に入り、結果的に「このフィールドは 8〜32 の長さを持つ必要があります。」と出力されます。

いつもやっていることなのにいざというときに思い出せない、こんなことで時間を使いたくないですね〜。ということで未来の自分のためのメモエントリでした。