INI形式のファイルを読み込み、読み込んだセクション・キー・値を一覧にして表示する例。 ここで紹介する実装では、INI形式の解析に正規表現を使う。 また、'#' および ';' で始まる行、および各行の ';' 以降をコメントとして扱う。
INI形式のファイルを読む
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
class Sample {
static void Main()
{
const string iniFile = @"test.ini";
// INIファイルを読み込み、各セクション毎に表示する
foreach (var section in ReadIni(iniFile)) {
Console.WriteLine("[{0}]", section.Key);
foreach (var pair in section.Value) {
Console.WriteLine(" <{0}>='{1}'", pair.Key, pair.Value);
}
}
}
private static Dictionary<string, Dictionary<string, string>> ReadIni(string file)
{
using (var reader = new StreamReader(file)) {
var sections = new Dictionary<string, Dictionary<string, string>>(StringComparer.Ordinal);
var regexSection = new Regex(@"^\s*\[(?<section>[^\]]+)\].*$", RegexOptions.Singleline | RegexOptions.CultureInvariant);
var regexNameValue = new Regex(@"^\s*(?<name>[^=]+)=(?<value>.*?)(\s+;(?<comment>.*))?$", RegexOptions.Singleline | RegexOptions.CultureInvariant);
var currentSection = string.Empty;
// セクション名が明示されていない先頭部分のセクション名を""として扱う
sections[string.Empty] = new Dictionary<string, string>();
for (;;) {
var line = reader.ReadLine();
if (line == null)
break;
// 空行は読み飛ばす
if (line.Length == 0)
continue;
// コメント行は読み飛ばす
if (line.StartsWith(";", StringComparison.Ordinal))
continue;
else if (line.StartsWith("#", StringComparison.Ordinal))
continue;
var matchNameValue = regexNameValue.Match(line);
if (matchNameValue.Success) {
// name=valueの行
sections[currentSection][matchNameValue.Groups["name"].Value.Trim()] = matchNameValue.Groups["value"].Value.Trim();
continue;
}
var matchSection = regexSection.Match(line);
if (matchSection.Success) {
// [section]の行
currentSection = matchSection.Groups["section"].Value;
if (!sections.ContainsKey(currentSection))
sections[currentSection] = new Dictionary<string, string>();
continue;
}
}
return sections;
}
}
}
INI形式のファイルを読む
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Text.RegularExpressions
Class Sample
Shared Sub Main()
Const iniFile As String = "test.ini"
' INIファイルを読み込み、各セクション毎に表示する
For Each section As KeyValuePair(Of String, Dictionary(Of String, String)) In ReadIni(iniFile)
Console.WriteLine("[{0}]", section.Key)
For Each pair As KeyValuePair(Of String, String) In section.Value
Console.WriteLine(" <{0}>='{1}'", pair.Key, pair.Value)
Next
Next
End Sub
Private Shared Function ReadIni(ByVal file As String) As Dictionary(Of String, Dictionary(Of String, String))
Using reader As New StreamReader(file)
Dim sections As New Dictionary(Of String, Dictionary(Of String, String))(StringComparer.Ordinal)
Dim regexSection As New Regex("^\s*\[(?<section>[^\]]+)\].*$", RegexOptions.Singleline Or RegexOptions.CultureInvariant)
Dim regexNameValue As New Regex("^\s*(?<name>[^=]+)=(?<value>.*?)(\s+;(?<comment>.*))?$", RegexOptions.Singleline Or RegexOptions.CultureInvariant)
Dim currentSection As String = String.Empty
' セクション名が明示されていない先頭部分のセクション名を""として扱う
sections(String.Empty) = New Dictionary(Of String, String)()
While True
Dim line As String = reader.ReadLine()
If line Is Nothing Then Exit While
' 空行は読み飛ばす
If line.Length = 0 Then Continue While
' コメント行は読み飛ばす
If line.StartsWith(";", StringComparison.Ordinal) Then
Continue While
Else If line.StartsWith("#", StringComparison.Ordinal) Then
Continue While
End If
Dim matchNameValue As Match = regexNameValue.Match(line)
If matchNameValue.Success Then
' name=valueの行
sections(currentSection)(matchNameValue.Groups("name").Value.Trim()) = matchNameValue.Groups("value").Value.Trim()
Continue While
End If
Dim matchSection As Match = regexSection.Match(line)
If matchSection.Success Then
' [section]の行
currentSection = matchSection.Groups("section").Value
If Not sections.ContainsKey(currentSection) Then
sections(currentSection) = New Dictionary(Of String, String)()
End If
Continue While
End If
End While
Return sections
End Using
End Function
End Class
例としてこのようなiniファイルの場合、
sample.ini
#
# ini file
#
; default section
username=test ; comment
password=xxxx ; comment
; setting for screen
[screen]
screenmode = fullscreen
screensize = 640x480
refresh-rate = 60Hz
; setting for input
[input]
shot=0
bomb = 1
skip=2
cancel = 3 ;
[screen]
screensize = 800x600
次のような実行結果となる。
実行結果
[] <username>='test' <password>='xxxx' [screen] <screenmode>='fullscreen' <screensize>='800x600' <refresh-rate>='60Hz' [input] <shot>='0' <bomb>='1' <skip>='2' <cancel>='3'