検索

キーワード


【Java】PropertiesクラスとResourceBundleクラス

  • 公開日:2021-05-06 06:09:53
  • 最終更新日:2021-05-08 06:28:12
【Java】PropertiesクラスとResourceBundleクラス

当記事では、java.util.Propertiesクラスの使い方について解説します。

プロパティファイルは、プログラムで用いる定数値や設定を記述したもので、キーと値のペアで構成されます。

プロパティファイルを使うと、ソースコードを再コンパイルせずにプログラム中の数値を変更出来たり、設定情報を保存することだできます。

当記事では、プロパティファイルの記法からjava.util.Propertiesクラスとjava.util.ResourceBundleクラスの使い方、プロパティファイルを編集する際に便利なプラグインについて紹介します。

システムプロパティについては、以下の記事で紹介しています。

【Java】システムプロパティからJVM上で設定されている改行コードなどの情報を確認する方法


プロパティファイルの記法

プロパティファイルは、以下のルールに基づいて記述されます。

  • ・拡張子は「.properties
  • ・一行ごとに一組の「キー」と「値」のセットを記述する
  • ・「キー」と「値」の間には「=」、「:」、半角スペースのいずれかのデミリタ(区切り文字)を入れる
  • ・行頭に「#」、「!」を記述することでその行をコメントアウトする

以下はプロパティファイルの記述例です。ファイル名は「sample.properties」です。

プロパティファイル内で日本語を用いる場合は、「Unicodeエスケープ方式(/u○○○○)」でエスケープを行わないと文字化けすることがあります。

#商品名:サンドイッチ
ProductName=\u30b5\u30f3\u30c9\u30a4\u30c3\u30c1
Price:100
!税率は%で表記
TaxRate 10

また、プロパティファイルはXML形式でも記述が可能です。


Propertiesクラスを使ってプロパティファイルからプロパティを読み込む

java.util.Propertiesクラスは、その名の通りプロパティファイルを扱うクラスで、主にプログラムの設定情報などを扱う際に使用します。

Propertiesクラスは、主に以下のようなメソッドを持ちます。

メソッド名戻り値の型説明
load( InputStream in
| Reader reader)
void入力バイトストリームまたは入力文字ストリームからプロパティファイルを読み込みます。
getProperty(String key
[,String defaultValue])
Stringkeyで指定したキーを持つプロパティを、プロパティファイルから見つけ出して値を返します。defaultValueを指定すると、指定したキーがプロパティファイル中に存在しなかったときの値を指定することが出来ます。
setProperty(
String key,
String value)
Objectキーと値を指定してプロパティに設定します。戻り値は変更前のキーの値です(値が存在しなかった場合はnullが返る)。
store(OutputStream out
| Writer writer, String comments)
void指定した出力バイトストリームまたは出力文字ストリームにプロパティファイルの内容を書き込みます。
また、ファイルの先頭にcommentsで指定したコメントと、プロパティファイルを書き込んだ時刻がコメント行として書き込まれます。
list(
PrintStream out)
void指定した出力ストリームに、プロパティのリストを出力します。
例えばoutにSystem.outを指定すれば、標準出力ストリームにプロパティのリストを出力できます。


Propertiesクラスを使ってプロパティファイルを読み込むサンプルコード

先ほどの「sample.properties」ファイルを使ってサンプルコードを記述しています。

#商品名:サンドイッチ
ProductName=\u30b5\u30f3\u30c9\u30a4\u30c3\u30c1
Price:100
!税率は%で表記
TaxRate 10

上記のプロパティファイルを、ソースコードと同じパッケージの配下に配置します。

以下のサンプルコードは、プロパティファイルの読み込み、変更、書き出しを行っています。

package properties;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;

public class PropatiesSample {
	public static void main(String[] args) {
		//読み込むプロパティファイルの入力ストリームと、プロパティファイルの書き込む先の出力ストリームを生成
		try (FileInputStream fis = new FileInputStream(new File("./src/properties/sample.properties"));
				FileOutputStream fos = new FileOutputStream(new File("./src/properties/sample2.properties"))) {
			
			//コンストラクタを呼び出す
			Properties properties = new Properties();
			
			//入力ストリームからプロパティファイルを読み込む
			properties.load(fis);
			
			//キーから値を取り出す
			System.out.println("商品名: " + properties.getProperty("ProductName"));
			System.out.println("価格 : " + properties.getProperty("Price"));
			System.out.println("税率 : " + properties.getProperty("TaxRate") + "%");
			
			//存在しないキーを呼び出したときにデフォルト値を返すようにする
			System.out.println("発売日: " + properties.getProperty("ReleaseDate", "未定"));
			
			//商品名と価格を変数に格納する
			String productName = properties.getProperty("ProductName");
			int price = Integer.parseInt(properties.getProperty("Price"));
			
			//価格と税率から税込み価格を計算
			System.out.println(productName + "の税込み価格は、" +
					price * (100 + Integer.parseInt(properties.getProperty("TaxRate"))) / 100 + "円です。");
			
			//TaxRateの値を8に変更
			properties.setProperty("TaxRate", "8");
			
			//出力ストリームにプロパティを書き込む
			properties.store(fos, "Comments");
			
			//TaxRateを変更した上で、価格と税率から税込み価格を計算
			System.out.println(productName + "の税込み価格は、" +
					price * (100 + Integer.parseInt(properties.getProperty("TaxRate"))) / 100 + "円です。");
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


Propertiesクラスを使ってプロパティファイルを読み込むサンプルコードの実行結果

コンソールに以下のように出力されます。

商品名: サンドイッチ
価格 : 100
税率 : 10%
発売日: 未定
サンドイッチの税込み価格は、110円です。
サンドイッチの税込み価格は、108円です。

また、出力されたプロパティファイル「sample2.properties」の内容は以下のようになっています。

#Comments
#Wed May 05 10:41:06 JST 2021
ProductName=\u30B5\u30F3\u30C9\u30A4\u30C3\u30C1
Price=100
TaxRate=8ぷ

「sample.properties」ファイルを編集し、price=200に変更した状態でサンプルコードを実行すると、以下のようにコンソールに表示されます。

商品名: サンドイッチ
価格 : 200
税率 : 10%
発売日: 未定
サンドイッチの税込み価格は、220円です。
サンドイッチの税込み価格は、216円です。こ

このように、ソースコード中の定数値を、ソースコードの外から変更することが可能です。


ResourceBundleクラスを使ってプロパティファイルからリソースバンドルを取得する

ResourceBundleクラスは、主にプログラム上で複数の地域や言語を扱う際に使用します。Propertiesクラスとの大きな違いは、読み込むファイル名を指定する方法です。

ResourceBundleクラスは、主に以下ようなメソッドを持ちます。

メソッド名戻り値の型説明
getBundle(  String baseName
[, Locale locale])
ResourceBundle指定された基底名とロケールからリソースバンドルを習得します。ロケールを指定しない場合は、デフォルトのロケールを呼び出します。
基底名は、「パッケージ名.リソースバンドル名」の形で記述します。
リソースバンドル名には拡張子の記述は不要で、
「基底名_言語コード_国・地域コード_バリアントコード」
という形で記述します。「_コード名」の部分は、右から順に省略可能です。
バリアントコードとは、言語コードや国・地域コードでは識別できない情報を識別するもので、たとえば和暦を使用する際にはlocaleに「ja_JP_JP」を指定します。
getString(
String key)
Stringkeyで指定したキーを持つプロパティを、リソースバンドルから見つけ出して値を文字列として返します。
getObject(
String key)
Objectkeyで指定したキーを持つプロパティを、リソースバンドルから見つけ出して値をオブジェクトとして返します。

ResourceBundleクラスを使ってプロパティファイルからリソースバンドルを取得するサンプルコード

以下の2つのプロパティファイルを、サンプルコードと同じ「properties」パッケージに配置します。「ja」は日本語、「zh」は中国語の言語コードです。

greeting_ja.properties

hello=こんにちは

greering_zh.properties

hello=你好

サンプルコードは以下の通りです。リソースバンドルを指定する際にはコード部分を省略して指定しています。

package properties;

import java.util.Locale;
import java.util.ResourceBundle;

public class ResourseBundleSample {
	public static void main(String[] args) {
		//デフォルトのロケール(日本語)のリソースバンドルを指定する
		ResourceBundle greetingResource_ja = ResourceBundle.getBundle(
				"properties.greeting");
		System.out.println(greetingResource_ja.getString("hello"));
		
		//中国語のリソースバンドルを指定する
		ResourceBundle greetingResource_zh = ResourceBundle.getBundle(
				"properties.greeting", Locale.CHINA);
		System.out.println(greetingResource_zh.getString("hello"));
		}
}


ResourceBundleクラスを使ってプロパティファイルからリソースバンドルを取得するサンプルコードの実行結果

コンソールに以下のように出力されます。

こんにちは
你好


ResourceBundleクラスを使ってクラスからリソースバンドルを取得する

Javaでは、リソースバンドルとしてプロパティファイルだけではなくクラスからも指定することが出来ます。クラスから指定することで、例えばデータベースを使ってプロパティの値を指定することも出来ます。ListResourceBundleクラスは、クラスをリソースバンドルとして利用する際に用いる、ResourceBundleクラスのサブクラスです。

ListResourceBundleクラスは、ResourceBundleクラスのサブクラスのです。そのためResourceBundleクラスが持つメソッドを持ち、それに加えて以下のメソッドを持ちます。

メソッド名戻り値の型説明
getContents()Object[][]リソースバンドルからキーと値がペアになったオブジェクトの二次元配列を取得します。

getContents()メソッドは抽象クラスであるため、リソースバンドルとして利用するクラス内で実装を行う必要があります。


ResourceBundleクラスを使ってクラスからリソースバンドルを取得するサンプルコード

以下のクラスファイルを「properties」パッケージの配下に用意します。「fr」はフランス語の言語コードです。

GreetingResourceClass_ja.java

package properties;

import java.util.ListResourceBundle;

public class GreetingResourceClass_ja extends ListResourceBundle{
	//キーと値のペアを二次元配列で指定
	private final Object[][] hello = { { "hello", "こんにちは" } };

	//getContentsメソッドをオーバーライド
	protected Object[][] getContents() {

		//上で指定した二次元配列を返す
		return hello;
	}
}

GreetingResourceClass_fr.java

package properties;

import java.util.ListResourceBundle;

public class GreetingResourceClass_fr extends ListResourceBundle{
	//キーと値のペアを二次元配列で指定
	private final Object[][] hello = { { "hello", "Bonjour" } };

	//getContentsメソッドをオーバーライド
	protected Object[][] getContents() {

		//上で指定した二次元配列を返す
		return hello;
	}
}

サンプルコードは以下の通りです。プロパティファイルの場合と同様、リソースバンドルを指定する際にはコード部分を省略して指定しています。

package properties;

import java.util.Locale;
import java.util.ResourceBundle;

public class ResourseBundleSample2 {
	public static void main(String[] args) {
		//デフォルトのロケール(日本語)のリソースバンドルを指定する
		ResourceBundle greetingResource_ja = ResourceBundle.getBundle(
				"properties.GreetingResourceClass");
		System.out.println(greetingResource_ja.getString("hello"));

		//フランス語のリソースバンドルを指定する
		ResourceBundle greetingResource_fr = ResourceBundle.getBundle(
				"properties.GreetingResourceClass", Locale.FRANCE);
		System.out.println(greetingResource_fr.getString("hello"));

	}
}


ResourceBundleクラスを使ってクラスからリソースバンドルを取得するサンプルコードの実行結果

コンソールに以下のように出力されます。

こんにちは
Bonjour


プロパティファイルを記述する際に便利なプラグイン

プロパティファイルに日本語などを記述する際にはunicodeエスケープを行う必要がありますが、いちいち変換するのは大変だと思います。そこで、そのまま日本語で記述しても問題なくプロパティファイルとして扱えるEclipseプラグインの紹介をしたいと思います。

導入方法

メニューバーからヘルプ→Eclipseマーケットプレイスとクリックし、検索ボックスに「property」と入力して検索します。

幾つか同様のプラグインがありますが、今回は「Simple Properties Editor」をインストールします。

Eclipseマーケットプレースで「property」と検索した画面

インストール後、Eclipseを再起動したら、プロパティファイルを「Simple Properties Editor」で開きます。

プロパティファイルを「Simple Properties Editor」で開く

Unicodeエスケープした部分が日本語になります。このプロパティファイルを読み込んでも、日本語部分の文字化けは起きません。

「Simple Properties Editor」を使ってプロパティファイルを開いた画面


まとめ

今回はプロパティファイルの記法、java.util.Propertiesクラスjava.util.ResourceBundleクラスの使い方、プロパティファイルを編集する際に便利なプラグインについて紹介しました。実際にプログラムを制作する際は、定数値をソースコード中に記述せずにプロパティファイル上に記述する場合がほとんどです。そのため、プロパティファイルの取り扱いはプログラム制作では避けては通れないものになっています。

プロパティファイルの扱い方を身に着け、用途に合わせた扱い方が出来るようになるとよいでしょう。

関連記事:

【Java】システムプロパティからJVM上で設定されている改行コードなどの情報を確認する方法


【著者】

ゆうさい

フォワードソフト株式会社のエンジニア。経験はまだ浅いものの、Java、Python、JavaScriptなど様々な言語の他、クラウドやネットワーク技術を勉強しています。PythonやVBAを使った自動化で楽をするのを考えるのが好きです。 Oracle Certified Java Programmer Gold SE 11、HTML5プロフェッショナル認定試験レベル2、AWSプラクティショナーなどの情報資格を保有しています。

よく読まれている記事
【Java】JSPでタグライブラリを使う(JSTL)

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様