Reading/writing an INI file

2018-12-31 04:25发布

Is there any class in the .NET framework that can read/write standard .ini files:

[Section]
<keyname>=<value>
...

Delphi has the TIniFile component and I want to know if there is anything similar for C#?

标签: c# .net ini
17条回答
只靠听说
2楼-- · 2018-12-31 04:58

You could use SharpConfig to read .cfg and/or .ini files. It's an easy to use config library for .NET.

查看更多
裙下三千臣
3楼-- · 2018-12-31 04:59

I want to introduce an IniParser library I've created completely in c#, so it contains no dependencies in any OS, which makes it Mono compatible. Open Source with MIT license -so it can be used in any code.

You can check out the source in GitHub, and it is also available as a NuGet package

It's heavily configurable, and really simple to use.

Sorry for the shameless plug but I hope it can be of help of anyone revisiting this answer.

查看更多
梦该遗忘
4楼-- · 2018-12-31 04:59

There is an Ini Parser available in CommonLibrary.NET

This has various very convenient overloads for getting sections/values and is very light weight.

查看更多
几人难应
5楼-- · 2018-12-31 05:03

The creators of the .NET framework want you to use XML-based config files, rather than INI files. So no, there is no built-in mechanism for reading them.

There are third party solutions available, though.

查看更多
后来的你喜欢了谁
6楼-- · 2018-12-31 05:04

I'm late to join the party, but I had the same issue today and I've written the following implementation:

using System.Text.RegularExpressions;

static bool match(this string str, string pat, out Match m) =>
    (m = Regex.Match(str, pat, RegexOptions.IgnoreCase)).Success;

static void Main()
{
    Dictionary<string, Dictionary<string, string>> ini = new Dictionary<string, Dictionary<string, string>>();
    string section = "";

    foreach (string line in File.ReadAllLines(.........)) // read from file
    {
        string ln = (line.Contains('#') ? line.Remove(line.IndexOf('#')) : line).Trim();

        if (ln.match(@"^[ \t]*\[(?<sec>[\w\-]+)\]", out Match m))
            section = m.Groups["sec"].ToString();
        else if (ln.match(@"^[ \t]*(?<prop>[\w\-]+)\=(?<val>.*)", out m))
        {
            if (!ini.ContainsKey(section))
                ini[section] = new Dictionary<string, string>();

            ini[section][m.Groups["prop"].ToString()] = m.Groups["val"].ToString();
        }
    }


    // access the ini file as follows:
    string content = ini["section"]["property"];
}

It must be noted, that this implementation does not handle sections or properties which are not found. To achieve this, you should extend the Dictionary<,>-class to handle unfound keys.


To serialize an instance of Dictionary<string, Dictionary<string, string>> to an .ini-file, I use the following code:

string targetpath = .........;
Dictionary<string, Dictionary<string, string>> ini = ........;
StringBuilder sb = new StringBuilder();

foreach (string section in ini.Keys)
{
    sb.AppendLine($"[{section}]");

    foreach (string property in ini[section].Keys)
        sb.AppendLine($"{property}={ini[section][property]");
}

File.WriteAllText(targetpath, sb.ToString());
查看更多
永恒的永恒
7楼-- · 2018-12-31 05:05

The code in joerage's answer is inspiring.

Unfortunately, it changes the character casing of the keys and does not handle comments. So I wrote something that should be robust enough to read (only) very dirty INI files and allows to retrieve keys as they are.

It uses some LINQ, a nested case insensitive string dictionary to store sections, keys and values, and read the file in one go.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

class IniReader
{
    Dictionary<string, Dictionary<string, string>> ini = new Dictionary<string, Dictionary<string, string>>(StringComparer.InvariantCultureIgnoreCase);

    public IniReader(string file)
    {
        var txt = File.ReadAllText(file);

        Dictionary<string, string> currentSection = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);

        ini[""] = currentSection;

        foreach(var line in txt.Split(new[]{"\n"}, StringSplitOptions.RemoveEmptyEntries)
                               .Where(t => !string.IsNullOrWhiteSpace(t))
                               .Select(t => t.Trim()))
        {
            if (line.StartsWith(";"))
                continue;

            if (line.StartsWith("[") && line.EndsWith("]"))
            {
                currentSection = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
                ini[line.Substring(1, line.LastIndexOf("]") - 1)] = currentSection;
                continue;
            }

            var idx = line.IndexOf("=");
            if (idx == -1)
                currentSection[line] = "";
            else
                currentSection[line.Substring(0, idx)] = line.Substring(idx + 1);
        }
    }

    public string GetValue(string key)
    {
        return GetValue(key, "", "");
    }

    public string GetValue(string key, string section)
    {
        return GetValue(key, section, "");
    }

    public string GetValue(string key, string section, string @default)
    {
        if (!ini.ContainsKey(section))
            return @default;

        if (!ini[section].ContainsKey(key))
            return @default;

        return ini[section][key];
    }

    public string[] GetKeys(string section)
    {
        if (!ini.ContainsKey(section))
            return new string[0];

        return ini[section].Keys.ToArray();
    }

    public string[] GetSections()
    {
        return ini.Keys.Where(t => t != "").ToArray();
    }
}
查看更多
登录 后发表回答