LoginSignup
5
10

More than 5 years have passed since last update.

iniファイルの読み書き用クラス

Posted at

はじめに

アプリケーションの設定値 (フォームの位置やサイズなど) を保存し, 次回起動時にこの設定値で起動する、ということを実施することがあると思います. この設定値を保存する形式は, .NET Frameworkアプリケーションではxml形式が推奨されていますが, 未だにini形式が好まれたりします.
そのため, iniファイルの読み書き用のクラスを作成してみました.

NativeMethods

使用するWin32 APIの定義はNativeMethodsクラスに以下のように定義します.

NativeMethods.cs
using System.Text;
using System.Runtime.InteropServices;

internal sealed class NativeMethods
{

    private NativeMethods() { }

    [DllImport("kernel32", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi, ExactSpelling = false)]
    internal static extern uint GetPrivateProfileString(
       [MarshalAs(UnmanagedType.LPWStr), In] string lpAppName,
       [MarshalAs(UnmanagedType.LPWStr), In] string lpKeyName,
       [MarshalAs(UnmanagedType.LPWStr), In] string lpDefault,
       [MarshalAs(UnmanagedType.LPWStr), Out] StringBuilder lpReturnString,
       uint nSize,
       [MarshalAs(UnmanagedType.LPWStr), In] string iniFilename);

    [DllImport("kernel32", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
    internal static extern int WritePrivateProfileString(
        [MarshalAs(UnmanagedType.LPWStr), In] string lpAppName,
        [MarshalAs(UnmanagedType.LPWStr), In] string lpKeyName,
        [MarshalAs(UnmanagedType.LPWStr), In] string lpString,
        [MarshalAs(UnmanagedType.LPWStr), In] string lpFileName);

}

Iniクラス

iniファイル読み書き用のクラスは次の通りです.

Ini
using System;
using System.ComponentModel;
using System.IO;
using System.Text;

public static class Ini
{

    /// <summary>
    /// INIファイルからキーの値を取得します
    /// <para>戻り値は, 取得が成功したかどうかを示します</para>
    /// </summary>
    /// <typeparam name="T">データ取得する型</typeparam>
    /// <param name="filePath">ファイルパス</param>
    /// <param name="sectionName">セクション名</param>
    /// <param name="keyName">キー名</param>
    /// <param name="defaultValue">初期値</param>
    /// <param name="outputValue">出力値</param>
    /// <returns>取得の成功有無</returns>
    public static bool TryGetValueOrDefault<T>(string filePath, string sectionName, string keyName, T defaultValue, out T outputValue)
    {

        outputValue = defaultValue;

        if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
            return false;

        var sb = new StringBuilder(1024);
        var ret = NativeMethods.GetPrivateProfileString(sectionName, keyName, string.Empty, sb, Convert.ToUInt32(sb.Capacity), filePath);
        if (ret == 0 || string.IsNullOrEmpty(sb.ToString()))
            return false;

        var conv = TypeDescriptor.GetConverter(typeof(T));
        if (conv == null)
            return false;

        try
        {
            outputValue = (T)conv.ConvertFromString(sb.ToString());
        }
        catch (NotSupportedException)
        {
            return false;
        }
        catch (FormatException)
        {
            return false;
        }

        return true;

    }

    /// <summary>
    /// INIファイルからキーの値を取得します
    /// </summary>
    /// <typeparam name="T">データ取得する型</typeparam>
    /// <param name="filePath">ファイルパス</param>
    /// <param name="sectionName">セクション名</param>
    /// <param name="keyName">キー名</param>
    /// <param name="defaultValue">初期値</param>
    /// <returns>キー値</returns>
    public static T GetValueOrDefault<T>(string filePath, string sectionName, string keyName, T defaultValue)
    {
        T ret = defaultValue;
        TryGetValueOrDefault(filePath, sectionName, keyName, defaultValue, out ret);
        return ret;
    }

    /// <summary>
    /// INIファイルにデータを書き込みます
    /// </summary>
    /// <param name="filePath">ファイルパス</param>
    /// <param name="sectionName">セクション名</param>
    /// <param name="keyName">キー名</param>
    /// <param name="outputValue">出力値</param>
    public static void SetValue(string filePath, string sectionName, string keyName, string outputValue) =>
        NativeMethods.WritePrivateProfileString(sectionName, keyName, outputValue, filePath);


}

使い方

WinFormsアプリケーションでフォームの位置・サイズをiniファイルへの読み書きするサンプルです.
アプリケーションと同一ディレクトリーにTest.iniが存在しているとし, このTest.iniに設定値を読み書きします. FormのLoadイベントでiniファイルの内容を読み込み, FormClosingイベントでiniファイルに書き込みしています.

サンプルアプリ
private void MainForm_Load(object sender, EventArgs e)
{
    StartPosition = FormStartPosition.Manual;

    //iniから前回のフォーム位置、サイズ取得
    var filePath = System.IO.Path.Combine(Environment.CurrentDirectory, "Test.ini");
    Left = Ini.GetValueOrDefault(filePath, Name, nameof(Left), 0);
    Top = Ini.GetValueOrDefault(filePath, Name, nameof(Top), 0);
    Width = Ini.GetValueOrDefault(filePath, Name, nameof(Width), 100);
    Height = Ini.GetValueOrDefault(filePath, Name, nameof(Height), 100);
}

private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
    //iniにフォーム位置、サイズ保存
    var filePath = System.IO.Path.Combine(Environment.CurrentDirectory, "Test.ini");
    Ini.SetValue(filePath, Name, nameof(Left), Left.ToString());
    Ini.SetValue(filePath, Name, nameof(Top), Top.ToString());
    Ini.SetValue(filePath, Name, nameof(Width), Width.ToString());
    Ini.SetValue(filePath, Name, nameof(Height), Height.ToString());
}

最後に

今回作成したIniクラスを使用することで簡易にiniファイルの内容を読み書きできるようになりました.

5
10
0

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
5
10