INI 是程序配置最常见的格式之一。虽然 .NET 没有内置的 INI 解析器,但自己实现一个轻量读写类并不复杂。下面的 IniFile 类支持分节解析、忽略大小写、默认值与保存回写,不依赖任何第三方库。

实现思路

Load 时逐行读取:以 [ 开头的是节名,其余按第一个等号拆分键值;注释行以分号或井号开头直接跳过。Get 取值带默认值,Set 修改或新增,Save 统一写回文件。

完整代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

public class IniFile
{
    private readonly Dictionary<string, Dictionary<string, string>> _data =
        new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);

    private string _path;

    public void Load(string path)
    {
        _path = path;
        _data.Clear();
        if (!File.Exists(path)) return;

        string section = "";
        foreach (string rawLine in File.ReadAllLines(path, Encoding.UTF8))
        {
            string line = rawLine.Trim();
            if (line.Length == 0 || line.StartsWith(";") || line.StartsWith("#")) continue;

            if (line.StartsWith("[") && line.EndsWith("]"))
            {
                section = line.Substring(1, line.Length - 2).Trim();
                Ensure(section);
            }
            else
            {
                int eq = line.IndexOf("=");
                if (eq <= 0) continue;
                string key = line.Substring(0, eq).Trim();
                string value = line.Substring(eq + 1).Trim();
                Ensure(section);
                _data[section][key] = value;
            }
        }
    }

    private void Ensure(string section)
    {
        if (!_data.ContainsKey(section))
            _data[section] = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
    }

    public string Get(string section, string key, string defaultValue = "")
    {
        return _data.ContainsKey(section) && _data[section].ContainsKey(key)
            ? _data[section][key] : defaultValue;
    }

    public void Set(string section, string key, string value)
    {
        Ensure(section);
        _data[section][key] = value;
    }

    public void Save()
    {
        var sb = new StringBuilder();
        foreach (var pair in _data)
        {
            sb.Append("[").Append(pair.Key).AppendLine("]");
            foreach (var kv in pair.Value)
                sb.Append(kv.Key).Append("=").AppendLine(kv.Value);
            sb.AppendLine();
        }
        File.WriteAllText(_path, sb.ToString(), Encoding.UTF8);
    }
}

class Program
{
    static void Main()
    {
        var ini = new IniFile();
        ini.Load("config.ini");
        Console.WriteLine(ini.Get("app", "title", "未设置"));

        ini.Set("app", "title", "我的程序");
        ini.Save();
    }
}

使用要点

  • 节与键名统一忽略大小写,取数更宽容;
  • 编码统一 UTF-8,避免中文乱码;
  • 想保留注释与空行,建议改用带标记的流式重写方案。

小结

该实现覆盖了绝大多数配置读写场景,若项目为 .NET Core 3.0 及以上,也可考虑官方 Microsoft.Extensions.Configuration.Ini 提供器。