Go to Contents Go to Java Page
J2SE 1.5 虎の穴
 
 

XML に対応した Properties

 
 
Tiger プロパティファイルを見たことありますか?
 
 

プロパティはアプリケーションの設定などによく使われていると思います。説明するより実際のファイルを見てみましょう。下のファイルは logging.properties ファイルです。見やすさのためにコメントを省略してあります。

handlers= java.util.logging.ConsoleHandler
.level= INFO
 
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
 
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

1 行は キー = 値 で構成されています。

このようなプロパティを扱うクラスが java.util.Properties クラスです。このクラス自体は太古の JDK 1.0 のころからあるので皆さんご存知だと思います。

しかし、最近の傾向からすると何でもかんでも XML、設定ファイルも XML になってきています。たとえば、logging API の対抗馬 Log4J の設定ファイルは XML になっています。

今までの Properties クラスでは XML は扱うことができなかったのですが、Tiger になってやっと XML の設定ファイルの読み書きができるようになったのです。

 

 
 
Tiger とりあえず、試してみよう
 
 

なにはともあれやってみましょう。

まずはプロパティの保存から。

サンプルのソース PropertiesSaveTest.java

ここでは単純なプロパティを XML のファイルにセーブしています。XML にセーブするには Properties#storeToXML メソッドを使用します。

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.util.Properties;
 
public class PropertiesSaveTest {
    public PropertiesSaveTest() {
        Properties prop = new Properties();
        prop.setProperty("ONE", "1");
        prop.setProperty("TWO", "2");
        prop.setProperty("THREE", "3");
        prop.setProperty("FOUR", "4");
 
        try {
            OutputStream stream = new FileOutputStream("temp.properties");
            prop.storeToXML(stream, "Temporary Properties");
            stream.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new PropertiesSaveTest();
    }
}

PropertiesSaveTest クラスを実行すると、system.properties ファイルが生成されるはずです。下のファイルは Windows XP で実行した場合のファイルです。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Temporary Properties</comment>
<entry key="TWO">2</entry>
<entry key="FOUR">4</entry>
<entry key="ONE">1</entry>
<entry key="THREE">3</entry>
</properties>

あっけなく XML でセーブされました。この XML を見てみるとプロパティは <entry> タグによって表されていることが分かります。キーは <entry> タグの key 属性、値が要素になっているようです。

このファイルの DTD は Properties クラスの JavaDoc に記載されています。

それでは次はロードです。

サンプルのソース PropertiesLoadTest.java

XML のプロパティファイルを読み込むには Properties#loadFromXML メソッドを使用します。

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.util.Properties;
 
public class PropertiesLoadTest {
    public PropertiesLoadTest(String filename) {
        Properties prop = new Properties();
 
        try {
            InputStream stream = new FileInputStream(filename);
            prop.loadFromXML(stream);
            stream.close();

            prop.list(System.out);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
 
    public static void main(String[] args) {
        new PropertiesLoadTest(args[0]);
    }
}

これを実行すると

C:\examples>java PropertiesLoadTest temp.properties
-- listing properties --
TWO=2
FOUR=4
ONE=1
THREE=3
  
C:\examples>

ちゃんと読み込めたようです。順序は保証されていないので、これはこれで OK です。

 

 
 
Tiger 今までの問題はどうなった
 
 

今までプロパティファイルを扱うときに一番問題だったというか面倒くさかったのは日本語の扱いです。

とうのはいままでプロパティファイルに記述できるのは文字コードは唯一 Unicode だけだったからです。日本語を入れたかったらシフト JIS や EUC で記述してから native2ascii コマンドで Unicode に変換しなければなりませんでした。

これは結構面倒です。

しかし、XML を扱えるということで光明が見えてきました。XML であれば文字コードをファイルの中で指定できるからです。

そこで、先ほどのプロパティファイルを次のように変更して PropertiesLoadTest クラスで読みこんでみました。

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Temporary Properties</comment>
<entry key="ONE">壱</entry>
<entry key="TWO">弐</entry>
<entry key="THREE">参</entry>
<entry key="FOUR">四</entry>
</properties>

ファイル名は temp2.properties にしてあります。

C:\examples>java PropertiesLoadTest temp2.properties
-- listing properties --
TWO=弐
ONE=壱
FOUR=四
THREE=参
  
C:\examples>

ただしく読み込めました。

セーブはどうでしょうか。

サンプルのソース PropertiesSaveTest2.java

文字コードを指定するには storeToXML メソッドの第 2 引数に文字コードを記述するようにします。

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.util.Properties;
 
public class PropertiesSaveTest2 {
    public PropertiesSaveTest2() {
        Properties prop = new Properties();
        prop.setProperty("ONE", "一");
        prop.setProperty("TWO", "二");
        prop.setProperty("THREE", "三");
        prop.setProperty("FOUR", "四");
 
        try {
            OutputStream stream = new FileOutputStream("temp3.properties");
            prop.storeToXML(stream, "Temporary Properties", "Shift_JIS");
            stream.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
 
    public static void main(String[] args) {
        new PropertiesSaveTest2();
    }
}

これを実行すると、次のようなファイルが生成されました。

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Temporary Properties</comment>
<entry key="TWO">二</entry>
<entry key="FOUR">四</entry>
<entry key="ONE">一</entry>
<entry key="THREE">三</entry>
</properties>

encodig が Shift_JIS になり、文字コードも Shift_JIS になっていました。

これで日本語のプロパティを扱うのも容易ですね。

 

 
 
Tiger おわりに
 
 

今まで日本語が扱いにくかったプロパティですが、XML をサポートすることによりずいぶん楽に日本語が扱えるようになりました。

しかし、まだ問題は残っています。ResourceBundle クラスや logging API も Properties クラスを使用するのですが、これらの API はまだ XML に対応した実装が行われていないようです。特に ResourceBundle クラスが問題ですね。

Tiger の正式版までにちゃんと XML に対応してくれることを望んでいます。

また、今の XML のプロパティファイルは単にテキストのプロパティファイルを XML にしただけなので、あまり XML の効果がでていません。

たとえば、文字列だけでなく、オブジェクトも入れられるようになればもっといいのにと思いませんか。たとえば次のようにリストを入れるとか。

<?xml version="1.0" encoding="Shift_JIS"?>
<!-- この形式は Tiger ではサポートしていません !! -->
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Temporary Properties</comment>
<entry key="Titles" type="java.util.List">
  <list>
    <item type="string">Generics</item>
    <item type="string">Metadata</item>
    <item type="string">拡張 for 文</item>
  </list>
</entry>
</properties>

JAXB を使えるようにすればこういうこともできると思うのですが、今のままだといささか中途半端な仕様になってしまっていると思います。

そう思うと、JAXB をなぜコアに入れなかったかという疑問も残ります。JAXM や JAX-RPC は入れなくてもいいとは思いますが、JAXB はぜひ取り込んでほしかったと思います。

 

今回使用したサンプルはここからダウンロードできます。

 

(Apr. 2004)

 
 
Go to Contents Go to Java Page