こんにちは。「Javaを復習する初心者」です。
今回はPropertiesクラスを利用して、テキストファイル「test.properties」に定義した値を読み取るサンプルを作成しました。
細かい説明をしてから最後に完成したサンプルを載せてます。
目次
Propertiesクラスの使い方概要
Propertiesクラスを使ってプロパティファイルから値を読み取るには、以下の流れになります。
- load()メソッド実行する。
- getProperty()メソッドの引数にキーを指定して、値を取得する。
今回はload()メソッドの引数にInputStreamReaderクラスのインスタンスを指定します。そのために、プログラミングはファイル読み取りの箇所から記述する必要があります。
FileInputStreamクラスのインスタンスを生成
まず、FileInputStreamクラスのインスタンスを生成します。このクラスのコンストラクタの引数にはプロパティファイルのパスを指定します。
例えば、以下のように記述します。
FileInputStream生成
String PROPERTIES_FILE_PATH = "file/test.properties";
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(PROPERTIES_FILE_PATH);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
上記例では「test.properties」がプロパティファイルです。Eclipseのプロジェクトの直下に「file」フォルダを作成し、「test.properties」ファイルを格納してあります。
パスを間違えていたり、ファイルを配置していなかった場合や、その他の理由でファイルが開けなかった場合では、FileNotFoundExceptionが発生します。その場合、catch節が実行されるので、コンソールに以下のように出力されます。
ファイルが開けなかった場合
java.io.FileNotFoundException: file\test.properties (指定されたファイルが見つかりません。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at test.Test.main(Test.java:20)
コンソールに何も出力されなければ、ファイルの読み取りは成功しています。
InputStreamReaderクラスのインスタンスを生成
上記プログラムで取得したFileInputStreamのインスタンスを使って、InputStreamReaderクラスのインスタンスを生成します。
コンストラクタは以下を使用します。
- InputStreamReader(InputStream in, Charset cs)
このコンストラクタでは、文字コードcsを使うInputStreamReaderを作成します。例えば、以下のように記述します。
ソース
String CHARSET_NAME ="UTF-8";
InputStreamReader inputStreamReader = null;
try {
inputStreamReader = new InputStreamReader(fileInputStream, CHARSET_NAME);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
上記では文字コード「UTF-8」をして指定ます。プロパティファイルがこの文字コードで保存されている前提です。サポート外の文字コードを指定すると、UnsupportedEncodingExceptionが発生します。例えば、以下のように出力されます。
文字コードがサポート外の場合
java.io.UnsupportedEncodingException: UTF-8A
at sun.nio.cs.StreamDecoder.forInputStreamReader(StreamDecoder.java:71)
at java.io.InputStreamReader.<init>(InputStreamReader.java:100)
at test.Test.main(Test.java:29)
上記では文字コードの指定でスペルミスがあったためにエラーが発生しています。
コンソールに何も出力されなければ、ファイルの読み取りは成功しています。
プロパティファイルを読み取る
InputStreamReaderのインスタンスを生成した後は、冒頭で紹介した手順で値を読み取ります。
例えば、test.propertiesが以下のような内容であるとします。
test.properties
#プロパティ
user=ユーザー01
pw=パスワード01
プロパティファイルでは次の様式でキーと値を一行に定義します。
- [キー]=[値]
上記例では以下のキーと値が定義されていることになります。
キー | 値 |
---|---|
user | ユーザー01 |
pw | パスワード01 |
今回は何らかのデータベース等にアクセスするためのユーザー名とパスワードを記載してあるという想定です。
キーを指定して値を取得するには以下のように記述します。
ソース
Properties properties = new Properties();
try {
properties.load(inputStreamReader);
} catch (IOException e) {
e.printStackTrace();
}
String user = properties.getProperty("user");
String pw = properties.getProperty("pw");
System.out.println("USER: " + user);
System.out.println("PW: " + pw);
load()メソッドはIOExceptionをスローする定義になっていますが、いつ発生するのかは分かりませんでした。実行した場合、以下のようにキーの値が出力されました。
結果
USER: ユーザー01
PW: パスワード01
上記は出力しているだけですが、データベース接続に利用したりするのが一般的だと思います。
専用のユーティリティクラスを作成する
PropertiesUtilクラスを作成することを考えてみました。以下のように作ってみました。
PropertiesUtil
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
public class PropertiesUtil {
private static final String PROPERTIES_FILE_PATH = "file/test.properties";
private static final String CHARSET_NAME ="UTF-8";
public static Properties getProperties() {
Properties properties = null;
try (InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(PROPERTIES_FILE_PATH), CHARSET_NAME)){
properties = new Properties();
properties.load(inputStreamReader);
} catch (IOException e) {
e.printStackTrace();
}
return properties;
}
}
上記ではtry-with-resources文を使っています。close処理についての心配はこの構文で不要になるようです。この記事の前半ではFileNotFoundExceptionとUnsupportedEncodingExceptionが発生することを書きましたが、両方ともIOExceptionの子クラスであるため、IOExceptionをキャッチする記述にまとめることが出来ます。
例外クラスの継承関係は以下のようになっています。
java.lang.Object └java.lang.Throwable └java.lang.Exception └java.io.IOException ├java.io.FileNotFoundException └java.io.UnsupportedEncodingException
catch節ではスタックトレースを出力していますが、このあたりは開発現場の方針次第で色々だと思います。
getPropertiesメソッドはエラーが発生しなければ、Propertiesクラスのインスタンスを返却しています。getPropertiesメソッド内でloadメソッドを呼び出しているため、getPropertiesメソッドの呼び出し側はProperties#getPropertyメソッドを使うだけで良いことになります。
以下は呼び出し側の例と実行結果です。
ソース
import java.util.Properties;
public class Test {
private static final String KEY_NAME_USER ="user";
private static final String KEY_NAME_PW ="pw";
public static void main(String[] args) {
Properties properties = PropertiesUtil.getProperties();
if (properties == null) {
System.out.println("プロパティファイル読み取り失敗");
return ;
}
String user = properties.getProperty(KEY_NAME_USER);
String pw = properties.getProperty(KEY_NAME_PW);
System.out.printf("%4s: %s", KEY_NAME_USER, user);
System.out.println();
System.out.printf("%4s: %s", KEY_NAME_PW, pw);
}
}
結果
user: ユーザー01
pw: パスワード01
キーの値を読み取れていることが出力結果から分かります。PropertiesUtilクラスにファイルのパスと文字コードの定義をしてあるので、呼び出し側は特にこれらを気にしなくて良いという状態になっています。