LoginSignup
1

More than 5 years have passed since last update.

【Java】【Android】iniファイルを読み込む

Posted at

00. はじめに

Javaで設定値をファイルに保存するには.propertiesファイルとして保存する、というやり方があります。
しかし、C++で作成したアプリをJavaで作り直すなどで.iniファイルを使用したい時があります(というか、この間あった)。
なので、ちょっと、読み込む処理を書いてみます。

01. 読み込み対象の.iniファイルについて

なんか.iniファイルって厳密なフォーマットがないようなので、今回は以下のフォーマットを対象にします。

  1. コメント行
    '#'で始まる行をコメント行として無視します。
    文途中からコメントを始められないこととします。
  2. セクション行
    '['で始まり、']'で終わる行をセクション行としてみなし、囲われた文字列をセクションとします。
    以降で検出されたパラメータは、このセクションに属するものとします。
  3. パラメータ行
    文中に'='がある行をパラメータ行とし、初めに登場した左側をkey、右側をvalueとします。
  4. 上記以外
    無視

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 投稿

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1