Challenge Engineer Life !

エンジニア人生を楽しみたい!仕事や趣味で学んだ技術的なことを書いていくブログです。

ResourceBundleでクラスパス上にない外部ファイルを指定する

最近Java EEを離れ気味でJava SEのコードを書いているのですが、その中で多言語対応が必要となりました。

前に「Java技術最前線」で読んだ気が…と思って再度確認したら、ResourceBundleの記事ありました。他もいくつか調べつつ、やはりこれを使うのが良さそうだなぁと。

で、NetBeansでまずは簡単にサンプルを。って数分で終わりますが。
Mavenで作ったプロジェクトにresourcesフォルダを追加して以下のような2つのプロパティファイルを置きました。

dictionary.properties

hello = HELLO!

dictionary_ja_JP.properties

hello = こんにちは

f:id:kikutaro777:20140218222905j:plain

で、以下のコードを実行

package jp.co.hoge.resourcebundlesample;

import java.util.ResourceBundle;

public class App 
{
    public static void main( String[] args )
    {
        ResourceBundle resouce = ResourceBundle.getBundle("dictionary");
        System.out.println(resouce.getString("hello"));
    }
}

結果は

f:id:kikutaro777:20140218223227j:plain

あっさり。

これをベースに、やりたいことは最初に挙げた記事群でほとんど満たされているのですが、今回作ってるものはフォルダ構成がガッチリと決められてしまっていて、プロパティファイルの置く位置が微妙。

例えば乱暴な例ですが、WindowsのD:\tmp\settingみたいな絶対パスとか、resourcesではない別のフォルダとかにプロパティを置きたい場合にResourceBundleでのプロパティファイル指定ってどうするんだろ…と。

で、StackOverflowに同じ質問が。

How to load a resource bundle from a file resource in Java?

ResourceBundle.getBundle()でクラスローダを指定できるシグネチャのメソッドがあって、そこにFileから取得したURL配列のURLClassLoaderを指定する方法。ほぉ…

以下コードで試してみました。さきほど置いたプロパティファイルを移動させて、実行ファイルとは別ドライブにフォルダを作って、そこに配置。

f:id:kikutaro777:20140218224223j:plain

プロパティファイル内の定義も少し変えて

dictionary.properties

hello = HELLO! from my drive 'D'

dictionary_ja_JP.properties

hello = こんにちは Dフォルダにあるプロパティだよ

みたいな。で以下のコードを実行。

package jp.co.hoge.resourcebundlesample;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Paths;
import java.util.Locale;
import java.util.ResourceBundle;

public class App 
{
    public static void main( String[] args ) throws MalformedURLException
    {
        File dicDir = Paths.get("D:\\tmp\\setting").toFile();
        URLClassLoader urlLoader = new URLClassLoader(new URL[]{dicDir.toURI().toURL()});
        ResourceBundle myResource 
            = ResourceBundle.getBundle("dictionary", Locale.getDefault(), urlLoader);
        System.out.println(myResource.getString("hello"));
    }
}

実行すると

f:id:kikutaro777:20140218224451j:plain

おお、ちゃんと読んでる。

一応言語も切り替えてみる。

f:id:kikutaro777:20140218230704j:plain

で、実行すると

f:id:kikutaro777:20140218230726j:plain

ja_JPのプロパティにあたらなかったので、dictionary.propertiesがちゃんと読まれたようです。

クラスローダまわりってあまりちゃんと理解してないので、こういうシンプルなのを例に理解を深めたい所(^^;

追記
Oracleの@den2snさんから以下コメントもらいました!

上記のサンプルはMavenを利用したプロジェクトだったのですがクラスパスの通し方がイマイチよくわからない…のでMaven使わないプロジェクト作って試してみました。

コードは最初の

package jp.co.hoge.resourcebundlesample;

import java.util.ResourceBundle;

public class App 
{
    public static void main( String[] args )
    {
        ResourceBundle resouce = ResourceBundle.getBundle("dictionary");
        System.out.println(resouce.getString("hello"));
    }
}

を利用して、プロパティファイルは後半のサンプル同様にDドライブの適当なフォルダへ。

コマンドラインだと-classpathを利用すると思うのですが

とのことで、NetBeansでプロパティからフォルダパスを追加しました。

f:id:kikutaro777:20140219004015j:plain

実行すると

f:id:kikutaro777:20140219004255j:plain

あっさり。こうすれば、わざわざ自分でURLClassLoaderないので楽ですね(^^;

Mavenはどうすればいいんだ…。

にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村