00. はじめに
Javaで設定値をファイルに保存するには.propertiesファイルとして保存する、というやり方があります。
しかし、C++で作成したアプリをJavaで作り直すなどで.iniファイルを使用したい時があります(というか、この間あった)。
なので、ちょっと、読み込む処理を書いてみます。
01. 読み込み対象の.iniファイルについて
なんか.iniファイルって厳密なフォーマットがないようなので、今回は以下のフォーマットを対象にします。
-
コメント行
'#'で始まる行をコメント行として無視します。
文途中からコメントを始められないこととします。 -
セクション行
'['で始まり、']'で終わる行をセクション行としてみなし、囲われた文字列をセクションとします。
以降で検出されたパラメータは、このセクションに属するものとします。 -
パラメータ行
文中に'='がある行をパラメータ行とし、初めに登場した左側をkey、右側をvalueとします。 -
上記以外
無視
02. 出来上がったものがこちらになります。
IniFileLoader.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* IniFileを読み込むローダー
*/
public class IniFileLoader {
// HashMap<section, HashMap<key, String>>とする
private HashMap<String, HashMap<String, String>> mDataMap;
// ファイルパス
private String mFilePath;
// load完了しているか
private boolean mIsLoaded = false;
/**
* 指定したファイルをロードする
*
* @param filePath ファイルパス
* @return ロードに成功したかどうか
*/
public boolean load(String filePath) {
mFilePath = filePath;
return loadProcess(filePath);
}
/**
* 前回ロードを試みたファイルをもう一度ロードする
*
* @return ロードに成功したかどうか
*/
public boolean reload() {
return isEmpty(mFilePath) && loadProcess(mFilePath);
}
private boolean loadProcess(String filePath) {
mIsLoaded = false;
mDataMap = new HashMap<>();
try {
FileReader fileReader = new FileReader(new File(filePath));
BufferedReader br = new BufferedReader(fileReader);
String line = br.readLine();
// セクション名
String section = null;
// キーバリュー
HashMap<String, String> map = new HashMap<>();
while (line != null) {
// 行頭、行末の空白を取り除く
line = line.trim();
// 空行
if (isEmpty(line)) {
// no process
}
// コメント行
else if (line.charAt(0) == '#') {
// no process
}
// セクション行
else if (line.charAt(0) == '[' && line.charAt(line.length() - 1) == ']') {
section = line.substring(1, line.length() - 1);
map = new HashMap<>();
}
// パラメータ行
else if (line.length() >= 3 && line.contains("=") && line.length() > line.indexOf("=") + 1) {
String key = line.substring(0, line.indexOf("="));
String value = line.substring(line.indexOf("=") + 1);
map.put(key, value);
mDataMap.put(section, map);
}
line = br.readLine();
}
br.close();
} catch (IOException e) {
return false;
}
mIsLoaded = true;
return true;
}
/**
* 読み込んだ結果を (section, (key, value)) の {@link HashMap} で返す
*
* @return 読み込んだ結果の {@link HashMap}
*/
public HashMap<String, HashMap<String, IniItem>> getAllDataMap() {
if (mIsLoaded) {
return mDataMap;
}
return null;
}
/**
* 読み込んだ結果の指定したセクションを(key, value)の {@link Map} で返す
*
* @param section セクション指定
* @return 読み込んだ結果の指定したセクション部
*/
public Map<String, String> getSectionDataMap(String section) {
if (mIsLoaded) {
return mDataMap.get(section);
}
return null;
}
/**
* 指定したセクション、指定したキーの値を返す
*
* @param section セクション指定
* @param key キー指定
* @return 指定したセクション、指定したキーの値
*/
public String getValue(String section, String key) {
if (mIsLoaded) {
HashMap<String, String> map = mDataMap.get(section);
if (map != null) {
return map.get(key);
}
}
return null;
}
/**
* 指定したセクションが読み込んだ結果にあるかを返す
*
* @param section セクション指定
* @return 存在する場合は {@code true}
*/
public boolean containsSection(String section) {
if (mIsLoaded) {
return mDataMap.containsKey(section);
}
return false;
}
/**
* 指定したセクションの、指定したキーが読み込んだ結果にあるかを返す
*
* @param section セクション指定
* @param key キー指定
* @return 存在する場合は {@code true}
*/
public boolean containsKey(String section, String key) {
if (mIsLoaded) {
HashMap<String, IniItem> map = mDataMap.get(section);
return map != null && map.containsKey(key);
}
return false;
}
/**
* {@code String} が空か判定する
*
* @param str 判定対象
* @return {@code String} が空ならば {@code true}
*/
private boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
}
1行ずつ読んで判定しているだけですね。
03. ライブラリにしたものがこちらになります。
ライブラリにしました。
一応、Androidでも使用できるようになっています。
98. 参考
[Java][サンプルコード] INIファイル読み書きライブラリを自作してみた | http://javasampleokiba.blog.fc2.com/blog-entry-27.html
99. 更新履歴
日付 | 内容 |
---|---|
2018/03/24 | 投稿 |