C Sharpの基礎 - INIファイル
ナビゲーションに移動
検索に移動
概要
INIファイルは、シンプルな設定ファイル形式であり、多くのアプリケーションで使用されている。
その構造は直感的で、セクションとキーおよび値のペアで構成されている。
基本的な構造として、INIファイルはセクションで始まり、その下にキーと値のペアが続く。
セクションは角括弧[]で囲まれ、キーと値はイコール記号=で区切られる。
例えば、以下に示すような形式になる。
[<セクション名>]
<キー名 1>=<値>
<キー名 2>=<値>
C#でINIファイルを読み書きするには、主に2つのアプローチがある。
- C#では、INIファイルを直接サポートする組み込みのクラスは存在しないため、
System.IO
名前空間のクラスを使用して開発者自身で実装する方法 - サードパーティ製のライブラリを使用する方法
開発者自身で実装する場合、File.ReadAllLines
メソッドを使用してファイルの内容を読み込み、文字列操作でセクション、キー、値を解析する。
書き込む場合は、File.WriteAllLines
メソッドを使用する。
サードパーティ製のライブラリを使用する場合、多くの選択肢があるが、人気のあるものの1つにini-parserライブラリが存在する。
これは、NuGetパッケージマネージャーを通じてインストールでき、INIファイルの読み書きを効率的に行うことができる。
INIファイルは簡単な設定の保存に便利であるが、複雑な構造や大量のデータを扱う場合は、XMLやJSON等の他の形式を使用することを推奨する。
実装する場合
INIファイルの読み込み
以下の例では、INIファイルを非同期で読み込みするクラスを定義している。
下記の特徴を以下に示す。
- 非同期処理
- ファイルの読み込みを非同期で行う。
- ストリーミング処理
- FileStreamクラス、StreamReaderクラスを使用してファイルをストリーミング処理する。
- これにより、大きなファイルでもメモリ効率よく処理することができる。
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
public class IniFileReader
{
// INIファイルの内容を保持する辞書
private Dictionary<string, Dictionary<string, string>> _iniContent;
public IniFileReader()
{
_iniContent = new Dictionary<string, Dictionary<string, string>>();
}
// INIファイルを非同期で読み込む
public async Task ReadIniFileAsync(string filePath)
{
try
{
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
string currentSection = "";
string line;
while ((line = await streamReader.ReadLineAsync()) != null)
{
line = line.Trim();
// コメント行 (; #) や空行を無視
if (string.IsNullOrWhiteSpace(line) || line.StartsWith(";") || line.StartsWith("#"))
continue;
// セクション行の処理
if (line.StartsWith("[") && line.EndsWith("]"))
{
currentSection = line.Substring(1, line.Length - 2);
if (!_iniContent.ContainsKey(currentSection))
_iniContent[currentSection] = new Dictionary<string, string>();
}
else if (line.Contains("="))
{ // キーおよび値ペアの処理
var parts = line.Split(new[] { '=' }, 2);
if (parts.Length == 2)
{
var key = parts[0].Trim();
var value = parts[1].Trim();
_iniContent[currentSection][key] = value;
}
}
}
}
}
catch (FileNotFoundException)
{
Console.WriteLine("指定されたファイルが存在しない");
}
catch (IOException ex)
{
Console.WriteLine($"ファイルの読み込み中にエラーが発生: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"予期せぬエラーが発生: {ex.Message}");
}
}
// 値を取得するメソッド
public string GetValue(string section, string key)
{
if (_iniContent.TryGetValue(section, out var sectionDict))
{
if (sectionDict.TryGetValue(key, out var value))
{
return value;
}
}
return null;
}
// 読み込んだINIファイルの内容を表示するメソッド
public void DisplayContent()
{
foreach (var section in _iniContent)
{
Console.WriteLine($"[{section.Key}]");
foreach (var kvp in section.Value)
{
Console.WriteLine($"{kvp.Key}={kvp.Value}");
}
Console.WriteLine();
}
}
}
上記のクラスを使用する場合は、以下に示すようにインスタンスを生成して、メソッドを実行する。
var iniReader = new IniFileReader();
// INIファイルの読み込み
await iniReader.ReadIniFileAsync("sample.ini");
// 値の取得
string value = iniReader.GetValue("セクション名", "キー名");
// 値の表示
iniReader.DisplayContent();
INIファイルの書き込み
以下の例では、INIファイルを非同期で書き込みするクラスを定義している。
下記の特徴を以下に示す。
- 非同期処理
- ファイルの読み込みを非同期で行う。
- ストリーミング処理
- FileStreamクラス、StreamWriterクラスを使用してファイルをストリーミング処理する。
- これにより、大きなファイルでもメモリ効率よく処理することができる。
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
public class IniFileWriter
{
// INIファイルの内容を保持する辞書
private Dictionary<string, Dictionary<string, string>> _iniContent;
public IniFileWriter()
{
_iniContent = new Dictionary<string, Dictionary<string, string>>();
}
// INIファイルを非同期で書き込む
public async Task WriteIniFileAsync(string filePath)
{
try
{
using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true))
using (var streamWriter = new StreamWriter(fileStream, Encoding.UTF8))
{
foreach (var section in _iniContent)
{
await streamWriter.WriteLineAsync($"[{section.Key}]");
foreach (var kvp in section.Value)
{
await streamWriter.WriteLineAsync($"{kvp.Key}={kvp.Value}");
}
await streamWriter.WriteLineAsync(); // セクション間に空行を挿入
}
}
Console.WriteLine("INIファイルの書き込みが完了");
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("ファイルへの書き込み権限がない");
}
catch (IOException ex)
{
Console.WriteLine($"ファイルの書き込み中にエラーが発生: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"予期せぬエラーが発生: {ex.Message}");
}
}
// 値を設定する
public void SetValue(string section, string key, string value)
{
if (!_iniContent.ContainsKey(section))
{
_iniContent[section] = new Dictionary<string, string>();
}
_iniContent[section][key] = value;
}
// セクションを追加する
public void AddSection(string section)
{
if (!_iniContent.ContainsKey(section))
{
_iniContent[section] = new Dictionary<string, string>();
}
}
// セクションを削除する
public void RemoveSection(string section)
{
_iniContent.Remove(section);
}
// キーを削除する
public void RemoveKey(string section, string key)
{
if (_iniContent.ContainsKey(section))
{
_iniContent[section].Remove(key);
}
}
}