Java の設定ファイル - Properties の使い方

この記事では、あなたの Java アプリケーションで利用できる 設定ファイルの使い方システムの設定情報の読み込み方法に説明します。

なぜ設定ファイルを使うのか?

アプリケーションを実行するときには、外部のリソースを参照する場合は少なくありません。例えば、 そのアプリケーションが参照するデータベースへの接続だったり、ファイルサーバーだったり、Webサービスだったりいろいろなリソースにアクセスする場合があります。

通常そうした外部リソースにアクセスするためには、リソースの場所の情報、ログイン情報、プロトコル情報などさまざな情報が必要になります。

ところが、外部のリソースへのアクセス情報などは、いつ変わるかわかりません。

もしアクセス情報などがソースコードに直接記述されていたら、 パスワードが変わるたびに、あなたのアプリケーションもソースコードを書き換えてビルドし直す必要がでてきてしまいます。

このため設定情報は、いつでも簡単に変更できるように、ソースコードに直接記述するのではなく、別途設定ファイルを用意して、そこに記述するのが望ましいです。

もちろん、設定値は外部リソースへのアクセス情報に限りません。フォントや配色などのユーザー毎の設定値なども、ユーザー毎の個別ファイルに記述することで、ユーザー毎に違ったエクスペリエンスを実現できます。

またそもそも、大変だ・大変じゃない、という手間の問題以上に、 アプリケーションを開発して、テスト環境で動作試験を行い、本番環境で利用を開始する、というような段取りを踏みたいときに、 それぞれ違うビルドのアプリケーションをテストしなければいけないのでは、そもそもテストになりません。

このため、設定情報とアプリケーションの実行ファイルは明確に分けておくのはとても大切なことなのです。

Properties ファイルの読み込みと保存

Java ではプロパティーズ (Properties) というクラスが用意されていて、これを用いることでキーと設定値のペアという形式で、設定情報の読み込みと保存を行うことができます。 尚、Properties クラスではキーも値も String 型を使います。

Properties ファイルの保存

それでは早速、Properties オブジェクトを作成し、値をいくつか設定して、それをファイルに保存してみましょう。

Properties オブジェクトでは好きな名前のキーに、好きな値を設定することができます。ただし、どちらも String 型の値とします。

次の例では country という名前のキーに USA という値を、 lang という名前のキーに English という値を設定しています。

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class TestApp1 {
  public static void main(String[] args) throws IOException {
    Properties settings = new Properties();
    settings.setProperty("country", "USA");
    settings.setProperty("lang", "English");

    FileOutputStream out = null;
    try {
      out = new FileOutputStream("foo.properties");
      settings.store(out, "Foo Properties");
    } finally {
      if (out != null) {
        out.close();
      }
    }
  }
}

Properties クラスの setProperty メソッドに、キーと値を渡すことで設定値をオブジェクトにセットします。

Properties は java.util.Hashtable から派生して、キー・バリューペアを実現しています。このため、Hashtable クラスの put メソッドを使うことでも、 背後のデータストアに値を設定することが可能です。しかし、あくまでもプロパティ値は String 型のみということになっているので、 setProperty メソッドでセットしましょう。

このコードでは foo.properties という名前のファイルに、Properties オブジェクトに格納された設定値を保存しています。

日本語のサンプルコードでは「適当な (なんでもいい) 変数名や文字列」の意味で "hoge" などと書いたりすることがありますが、 アメリカでは主に foo、bar、baz などがよく使われます。こうした文字をメタ構文変数 (metasyntactic variable) などと言います (RFC 3092)。

上の例ではファイル名として "foo.properties" としていますが、そのようなファイル名にしないといけないわけではなく「適当な名前をつけました」程度の意味になります。 実際に設定ファイルを開発する場合には、意味のある名前を設定してください。

Properties オブジェクトの保存には、store メソッドに出力 I/O ストリームを渡して呼び出します。 ここでは FileOutputStream オブジェクトを渡しているので、そのストリームに関連付けされたファイルに Properties オブジェクトの内容が保存されます。

上のコードを実行すると現在のディレクトリに、foo.properties という名前のテキストファイルが作成され、 中身は次のような内容になります。# で始まる行はコメント行です。

#Foo Properties
#Wed Sep 15 11:05:49 PDT 2019
lang=English
country=USA

プログラム内で設定した、lang キーに English という値、 さらに country キーに USA という値が正しく保存されていますね。

Properties ファイルの読み込み

上で作成した Properties ファイル foo.properties を読み込みましょう。

Properties クラスには、Properties ファイルを読み込むための load メソッドが用意されています。 load メソッドに 入力 I/O ストリームを渡して呼び出すことで、簡単に I/O ストリームから Properties オブジェクトを作成できます。

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class TestApp2 {
  public static void main(String[] args) throws IOException {
    // Properties の読み込み
    Properties settings = new Properties();
    FileInputStream in = null;
    try {
      in = new FileInputStream("foo.properties");
      settings.load(in);
    } finally {
      if (in != null) {
        in.close();
      }
    }

    // lang の値を出力
    String lang = settings.getProperty("lang");
    System.out.println("lang = [" + lang + "]");

    // 試しに設定ファイルにないキーを読み込む
    String xyz = settings.getProperty("xyz");
    System.out.println("xyz = [" + xyz + "]");

    // 全ての設定を出力
    settings.list(System.out);
  }
}

上で作成した foo.properties という名前の Properties ファイルが存在するときに、 これを実行すると、次の結果を得ます。

lang = [English]
xyz = [null]
-- listing properties --
lang=English
country=USA

ここでは、Properties ファイル作成時に設定した lang キーに対応する値を読み込んでいます。 さらに、存在しないキーを呼び、どうなるか見ています。キーが存在しない場合は、null が返ることがわかります。

Properties クラスの list メソッドを呼ぶと、設定値を全て出力します。

XML 設定ファイルの読み込みと保存

上の例ではキー・値ペアが記載された単純な設定ファイル (Properties ファイル) から Properties オブジェクトを作成したり、 Properties オブジェクトから、Properties ファイルを簡単に出力できることをみました。

<キー>=<値> という形式はとても単純でわかりやすいので、多くの場合でこの形式で問題ないはずです。

しかし、設定値を他のシステムから読み出す必要がある場合は XML 形式で保存しておくと、XML のパーサーが利用できるので便利なことがあります。

XML 設定ファイルの保存

ここでは Properties を XML ファイルに出力する例を紹介します。基本的に内容は上記と同じです。

XML 形式で保存するには Properties クラスの storeToXML メソッドに、 出力 I/O ストリームを渡して呼び出します。

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class TestApp1x {
  public static void main(String[] args) throws IOException {
    Properties settings = new Properties();
    settings.setProperty("country", "USA");
    settings.setProperty("lang", "English");

    FileOutputStream out = null;
    try {
      out = new FileOutputStream("foo.properties.xml");
      settings.storeToXML(out, "Foo Properties");
    } finally {
      if (out != null) {
        out.close();
      }
    }
  }
}

この結果、次のような XML 形式の Properties ファイルが作成されます。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Foo Properties</comment>
<entry key="lang">English</entry>
<entry key="country">USA</entry>
</properties>

XML 設定ファイルの読み込み

上で作成した XML 形式の Properties ファイルを読み込みましょう。

XML 形式の Properties ファイルを読み込みためには、 Properties クラスの loadFromXML メソッドが使えます。

loadFromXML に入力 I/O ストリームを渡して呼び出すと、その I/O ストリームからデータを取得して、Properties オブジェクトを再構築します。

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class TestApp2x {
  public static void main(String[] args) throws IOException {
    // Properties の読み込み
    Properties settings = new Properties();
    FileInputStream in = null;
    try {
      in = new FileInputStream("foo.properties.xml");
      settings.loadFromXML(in);
    } finally {
      if (in != null) {
        in.close();
      }
    }

    // lang の値を出力
    String lang = settings.getProperty("lang");
    System.out.println("lang = [" + lang + "]");

    // 試しに設定ファイルにないキーを読み込む
    String xyz = settings.getProperty("xyz");
    System.out.println("xyz = [" + xyz + "]");

    // 全ての設定を出力
    settings.list(System.out);
  }
}

XML 形式の Properties ファイルを読み込んだ結果は、次のように出力されました。

lang = [English]
xyz = [null]
-- listing properties --
lang=English
country=USA

ここでも list メソッドを使って、リスト表示を出力しています。

システム設定の読み込み

Java ではシステムの設定も Properties オブジェクトで取得できます。

System.getProperties() メソッドを使うと、システムの設定情報の詰まった Properties オブジェクトが取得できます。 このオブジェクトを System Properties (システム・プロパティーズ) といいます。

システムプロパティーズの使い方

次の例では、System Properties オブジェクトを取得し、そこからホームディレクトリの設定を出力しています。

そして、さらに Properties クラスの list メソッドでプロパティに設定された設定値を全てリスト表示しています。

import java.util.Properties;

public class TestApp3 {
  public static void main(String[] args) {
    // システムの Properties を取得
    Properties properties = System.getProperties();
    // ホームディレクトリの出力
    System.out.println(properties.getProperty("user.home"));
    // 全ての設定を出力
    properties.list(System.out);
  }
}

私の環境でこれを実行すると、次のような結果が出力されました。

/Users/keisukeo
-- listing properties --
java.runtime.name=OpenJDK Runtime Environment
sun.boot.library.path=/Library/Java/JavaVirtualMachines/ama...
java.vm.version=25.222-b10
gopherProxySet=false
java.vm.vendor=Amazon.com Inc.
java.vendor.url=https://aws.amazon.com/corretto/
path.separator=:
...

最初の /Users/keisukeo がホームディレクトリの出力結果です。 そのあとは、list メソッドの出力結果です。

起動パラメータでシステムプロパティを渡す

System Properteis は上で説明したように、基本的にシステム全体の設定を取得するものです。 しかし、ある時だけ異なる値をシステムプロパティとして渡すことも可能です。

プログラム起動時に、システムプロパティ値を渡すには起動オプションを 使います。

java コマンドで -D<キー名>="値" のとして値を渡すと、 それがシステムプロパティーズのひとつとして、設定されます。

java -jar -Dxyz="foo" TestApp3.jar
...
xyz=foo

既存のシステムプロパティ値を起動オプションで設定すると、オプションの値でシステムプロパティが上書きされます。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Java 入門