プログラムを実行する際のパラメータを指定する方法は、何通りかあります。
ソースに書いておくのは、 パラメータの値が変わるごとに再コンパイルが必要になってしまうので論外です。 コマンドライン引数で与えるのが最も簡便ですが、 パラメータ自身を保存する仕組みがないという欠点があります。
Java ではプロパティファイルという仕組みにより、 キー(key)と値(value)の組による情報をファイルに読み書きすることができます。 プロパティファイルは、「キー=値」の形式で記述されたテキストファイルです。
id=mlab url=http://www.mlab.im.dendai.ac.jp/
プロパティファイルはアプリケーションの設定ファイルなどに利用されます。 構造が単純なため、複雑な情報を保存するのには向いていません。 属性名に階層情報を含ませるなどの工夫が必要になります。
また、英数字(ISO 8859_1)以外の文字をそのまま記述することができないことにも注意が必要です。
JDK 1.5 より、シンプルなXML形式も使えるようになりました。 XML形式を使う場合には文字コードとして UTF-8 も利用できます。
プロパティファイルを扱うクラスは java.util.Properties です。 メソッド load で読み込み、メソッド store で書き出します。 load をすると、 ファイル内に記述されているキーと値の組すべてが Hashtable というデータ構造でメモリに格納されます。 キーに対する値を読み出したり登録したりする操作はメモリ上のデータに対して実行されるので、 更新した結果を保存したい場合には store で元のファイルを上書きする必要があります。
test.properties として、以下の内容のテキストファイルを用意しておきます。
university=Tokyo Denki Univ. faculty=Science and Technology for Future Life
以下は、コマンドライン引数で指定されたファイルから内容を読みとり、 その内容を表示するプログラムです。
import java.io.*; import java.util.Properties; class PropertiesReader { public static void main(String[] args) { String filename = args[0]; // プロパティファイルのファイル名 Properties conf = new Properties(); try { conf.load(new FileInputStream(filename)); } catch (IOException e) { System.err.println("Cannot open " + filename + "."); e.printStackTrace(); System.exit(-1); // プログラム終了 } // 読み込み System.out.println(conf.getProperty("university")); System.out.println(conf.getProperty("faculty")); } }
PropertiesReader.java (utf-8)
以下のように実行します。
$ java PropertiesReader test.properties
以下は、コマンドライン引数で指定されたファイルから内容を読みとり、それに1組の情報を追加して上書きするプログラムです。
import java.io.*; import java.util.Properties; public class Configuration { private Properties conf; public Configuration(String filename){ conf = new Properties(); try { conf.load(new FileInputStream(filename)); } catch (IOException e) { System.err.println("Cannot open " + filename + "."); e.printStackTrace(); } } public String getProperty(String key) { if(conf.containsKey(key)) return conf.getProperty(key); else { System.err.println("Key not found: " + key); return ""; } } public void addProperty(String key, String value) { if(conf.containsKey(key)) System.err.println("Key already exists: " + key); else { conf.setProperty(key, value); } } public void store(String filename, String comments) { try { conf.store(new FileOutputStream(filename), comments); } catch (IOException e) { System.err.println("Cannot open " + filename + "."); e.printStackTrace(); } } public void storeToXML(String filename, String comments) { try { conf.storeToXML(new FileOutputStream(filename), comments); } catch (IOException e) { System.err.println("Cannot open " + filename + "."); e.printStackTrace(); } } public static void main(String[] args) { Configuration conf = new Configuration(args[0]); // 読み込み System.out.println(conf.getProperty("university")); System.out.println(conf.getProperty("faculty")); // 追加 conf.addProperty("division", "Information Systems and Multimedia Design"); // 説明を指定して保存 conf.store(args[0], "configurations"); //conf.storeToXML(args[0] + ".xml", "configurations"); } }
Configuration.java (utf-8)
Configuration.java (euc-jp)
以下のように実行します。
$ java Configuration test.properties
test.properties の内容の変化を確認しましょう。
上記 Configuration クラスを外部から利用してもよいでしょう。 例えば、Configuration.java と同じディレクトリにある Foo.java からは次のように使えます。
// プロパティファイルの仕組みを組み込みたい自分のプログラムの例 // 同じディレクトリに Configuration.java があるとする。 class Foo { public static void main(String[] args) { Configuration conf = new Configuration("test.properties"); // 読み込み System.out.println(conf.getProperty("university")); System.out.println(conf.getProperty("faculty")); } }
Configuration クラスを、import することなしに使用しています。 通常、同じディレクトリ(この場合、デフォルトパッケージ)にある別のクラスは、 import しなくても使用することができます。
test.xml として、以下の内容のテキストファイルを用意しておきます。
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>ソーシャルブックマーク</comment> <entry key="sitename1">はてなブックマーク</entry> <entry key="url1">http://b.hatena.ne.jp/</entry> <entry key="sitename2">livedoor クリップ</entry> <entry key="url2">http://clip.livedoor.com/</entry> </properties>
以下は、コマンドライン引数で指定されたファイルから内容を読みとり、それに1組の情報を追加して上書きするプログラムです。
import java.io.*; import java.util.Properties; public class ConfigurationXML { private Properties conf; public ConfigurationXML(String filename){ conf = new Properties(); try { conf.loadFromXML(new FileInputStream(filename)); } catch (IOException e) { System.err.println("Cannot open " + filename + "."); e.printStackTrace(); } } public String getProperty(String key) { if(conf.containsKey(key)) return conf.getProperty(key); else { System.err.println("Key not found: " + key); return ""; } } public void addProperty(String key, String value) { if(conf.containsKey(key)) System.err.println("Key already exists: " + key); else { conf.setProperty(key, value); } } public void storeToXML(String filename, String comments) { try { conf.storeToXML(new FileOutputStream(filename), comments); } catch (IOException e) { System.err.println("Cannot open " + filename + "."); e.printStackTrace(); } } public static void main(String[] args) { ConfigurationXML conf = new ConfigurationXML(args[0]); // 読み込み System.out.println("sitename1: " + conf.getProperty("sitename1")); System.out.println("url1: " + conf.getProperty("url1")); // 追加 conf.addProperty("sitename3", "delicious"); conf.addProperty("url3", "http://www.delicious.com/"); // 説明を指定して保存 conf.storeToXML(args[0], "ソーシャルブックマーク"); } }
ConfigurationXML.java (utf-8)
ConfigurationXML.java (euc-jp)
以下のように実行します。
$ java ConfigurationXML test.xml
test.xml の内容の変化を確認しましょう。
特にクラスローダの使い方については、確認しておくと良いでしょう。