65.9K
CodeProject 正在变化。 阅读更多。
Home

C# INI 文件解析器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (24投票s)

2024年8月29日

MIT

17分钟阅读

viewsIcon

25186

downloadIcon

794

一个基于正则表达式、无集合的 C# INI 文件解析器,在编辑条目时保留原始文件格式。

引言

解析 INI 文件是在处理配置时编程中相当常见的任务。INI 文件简单易懂,对人类和机器都友好。实现此功能有几种主要方法:

  • 使用字符串操作函数手动解析。这种方法在处理各种 INI 文件格式时具有最大的灵活性,但实现起来需要更多的工作。
  • 使用各种 API 的模块。它们提供现成的函数来读取、写入和处理 INI 格式的数据。这是一种更简单快捷的方法,但受限于库本身的功能,并且还会使项目变得平台依赖。
  • 使用常见的配置文件处理库进行解析,例如 Python 中的 configparser 或 .NET 中的 ConfigurationManager。这种方法是通用的,但可能不如专用解决方案灵活。
  • 使用正则表达式进行处理。

在本文中,我将介绍如何使用 C# 中的正则表达式来解析 INI 文件。这种方法提供了更大的灵活性和对处理逻辑的定制。

正则表达式需要对语法有更深入的了解,但通过它们,您无需集合即可修改现有条目并添加新条目。这种方法提供了高性能、灵活性和保留原始格式,使其成为使用单一工具处理各种格式的 INI 文件的有效解决方案。 但是,在深入文章之前,我想回答您可能有的一个问题。

在 21 世纪,为什么还需要解析 INI 文件?

有一种观点认为 INI 文件已经过时,不适合存储参数。我不会争论这个说法,但我会给出几个使用 INI 文件合理的例子,并且是最佳解决方案:

  1. 如果您的软件使用命令行,通过 INI 文件分组和批量传递大量参数会更方便。
  2. 如果您的软件使用接受 INI 参数的第三方实用程序。
  3. 如果您的软件参数很少,并且没有“设置”窗口或任何图形界面。
  4. 如果您需要能够以用户可理解的格式导出和导入参数到文件。
  5. 只是作为备份选项,或者向过去致敬,那时草地更绿,我们更年轻,Doom 从软盘安装,参数通过 INI 传递。

INI 文件格式

这种格式相当简单,并且对大多数开发人员来说已经很熟悉了。总的来说,它是由等号分隔的键值对列表,称为参数。为了方便起见,参数被分组到节中,节用方括号括起来。然而,尽管如此,仍然存在一些细微差别和细微差异,因为没有严格定义单一标准。如果我创建一个新的解析器,我的目标是使其通用,以便它尽可能高效地提取信息,因此在编写用于处理 INI 文件的通用解析器时,必须考虑到这些特性。

例如,可以使用不同的符号来表示注释,最常见的选项是井号(hash)或分号,以及键和值之间的各种分隔符。除了普通的等号,在这种情况下有时也会使用冒号。也有一些文件没有节,只有键值对。不同的系统可能使用不同的字符来终止行。对于“Key”和“key”是否应被视为不同或不区分大小写地视为相同,并没有明确定义。文件可能包含语法错误或任何未定义的数据,但这不应妨碍正确解析内容的有效部分。

在存储字符串数组方面也没有达成共识。一些标准允许多个同名键,另一些则允许使用转义字符来分隔参数值中的字符串。尽管大多数时候解析器会提取找到的第一个单个值。我们的解析器可以同样好地处理所有这些任务。

下面是使用流行的文本编辑器进行的语法高亮示例。如您所见,其格式不为节名或条目值后面的注释提供支持。为什么不呢?

正则表达式

经过大量研究,我提出了以下正则表达式,它允许我确定 INI 文件中每个字符的含义。整体如下:
(?=\S)(?<text>(?<comment>(?<open>[#;]+)(?:[^\S\r\n]*)(?<value>.+))|(?<section>(?<open>\[)(?:\s*)(?<value>[^\]]*\S+)(?:[^\S\r\n]*)(?<close>\]))|(?<entry>(?<key>[^=\r\n\ [\]]*\S)(?:[^\S\r\n]*)(?<delimiter>:|=)(?:[^\S\r\n]*)(?<value>[^#;\r\n]*))|(?<undefined>.+))(?<=\S)|(?<linebreaker>\r\n|\n)|(?<whitespace>[^\S\r\n]+)

在我们开始编写代码之前,我想分解一下解析正则表达式本身,并解释每个部分的作用。

  1. (?=\S) 是一个正向先行断言,它检查下一个字符不是空白字符。这是为了跳过行开头的空白字符。

  2. (?<text>....) 是一个命名组,用于捕获文件的文本块。这将使我们能够获得文件的全部内容以供进一步分析。

  3. (?<comment>(?<open>[#;]+)(?:[^\S\r\n]*)(?<value>.+)) 是一个命名组,用于捕获文件中的注释。它由以下部分组成:

    • (?<open>[#;]+) 是一个捕获一个或多个“#”或“;”字符的组,表示注释的开始。
    • (?:[^\S\r\n]*) - 是一个捕获所有空白字符(不包括换行符)的字符组。这是处理行内缩进的方式。
    • (?<value>.+) - 一个捕获行尾所有字符的组,即整个注释文本。
  4. (?<section>(?<open>\[)(?:\s*)(?<value>[^\]]*\S+)(?:[^\S\r\n]*)(?<close>\])) - 是一个捕获节的命名组。它由以下部分组成:

    • (?<open>\[) - 一个捕获“ [ ”字符的组,表示节的开始。
    • (?:\s*) - 一个捕获零个或多个空白字符的组。
    • (?<value>[^\]]*\S+) - 一个捕获一个或多个非空白字符(不包括“]”字符)的组。
    • (?:[^\S\r\n]*) - 再次,一个捕获缩进的组。
    • (?<close>\]) 是一个捕获“]”字符的组,它标记节的结束。
  5. (?<entry>(?<key>[^=\r\n\[\]]*\S)(?:[^\S\r\n]*)(?<delimiter>:|=)(?:[^\S\r\n]*)(?<value>[^#;\r\n]*)) 是一个捕获条目(键值对)的命名组。它由以下部分组成:

    • (?<key>[^=\r\n\[\]]*\S) 是一个捕获一个或多个非空白字符(不包括“=”、“换行符”和“[”字符)的组。
    • (?:[^\S\r\n]*) - 缩进,见上文。
    • (?<delimiter>:|=) 是一个捕获分隔键和值的“:”或“=”字符的组。
    • (?:[^\S\r\n]*) - 缩进。
    • (?<value>[^#;\r\n]*) 是一个捕获零个或多个字符(不包括“#”、“;”、换行符)的组。
  6. (?<undefined>.+) 是一个命名组,用于捕获未匹配前面组的任何未定义文本部分。

  7. (?<=\S) 是一个正向后行断言,它检查前面的字符不是空白字符。这是为了跳过行尾的空白字符。

  8. (?<linebreaker>\r\n|\n) 是一个命名组,用于捕获换行符(“\r\n”或“\n”)。

  9. (?<whitespace>[^\S\r\n]+) 是一个命名组,用于捕获行开头和结尾的缩进。

这是一个非常详细且精心设计的正则表达式,旨在准确解析 INI 文件的结构并从中提取所有必要组件(节、键、值、注释等)。它可以处理 INI 文件的各种格式变体,并提供一种健壮且灵活的解析方式。

看看这个正则表达式如何解析上面的配置文件。

您可以使用此 链接 尝试使用此正则表达式。

C# 编码

为了解决使用正则表达式解析 INI 文件的问题,我创建了 IniFile 类。该类将负责使用正则表达式读取和解析 INI 文件内容,以提取键、值和节。该类具有加载文件、获取节列表、按键获取值以及将更改写回文件的功能。通过使用正则表达式,IniFile 可以处理各种配置文件格式,包括带有注释、缩进、空格、语法错误和其他功能的。这将使解析器更加灵活和通用。要使用该类,您需要向其传递一个包含 INI 文件数据和解析设置的字符串或流。

看看如何使用 IniFile 类读取与上一个示例相同的配置文件。

var iniFile = IniFile.Load("config.ini");
// "Empty" section
string keyAboveSection = iniFile.ReadString(null, "key");
// Section1 contains integer values.
int num1 = iniFile.ReadInt32("Section1", "number1"); // Ignoring case available.
int num2 = iniFile.Read<int>("Section1", "Number2"); // The generic methods have been implemented.
// Section2 contains multiline content.
double pi = iniFile.ReadDouble("Section2", "NumberPI");
string singleString = iniFile["Section2", "SingleString"]; // The indexer is ready to use.
string multiString = iniFile.ReadString("Section2", "MultiString");
string[] arrayString = iniFile.ReadStrings("Section2", "ArrayString");
// Section3 contains more various types.
Encoding encoding = iniFile.Read<Encoding>("Section3", "encoding", 
                                           Encoding.UTF8, new CustomEncodingConverter);
CultureInfo culture = iniFile.Read<CultureInfo>("Section3", "culture", 
                                           CultureInfo.InvariantCulture);
Uri uri = iniFile.Read<Uri>("Section3", "url");

很神奇,对吧?让我们看看这是如何实现的,以及该类还提供哪些其他功能。

类的主要功能

  1. 支持各种加载和保存方法:该类提供了从字符串、流或文件加载 INI 文件的方法,以及将它们保存到流或文件的方法。
  2. 使用正则表达式:使用正则表达式可以灵活高效地处理各种 INI 文件格式,包括支持注释、节和键值对。与使用手动字符串处理相比,这使得代码更紧凑且易于扩展。
  3. 不依赖集合:该类不使用集合来存储 INI 文件数据,这使其内存效率更高,并且简化了处理大文件的操作。
  4. 保留原始格式:在修改现有条目或添加新条目时,该类会保留原始 INI 文件格式,包括注释、空格和换行符的位置。这有助于保持文件的可读性和结构。
  5. 支持转义字符:该类提供了处理键值中转义字符的功能。这允许正确处理制表符、换行符等特殊字符。
  6. 自动检测换行符:该类自动检测 INI 文件中的换行符类型(CRLF、LF 或 CR)并在保存更改时使用它们。如果没有找到新行,将使用当前操作系统的默认选择。
  7. 自动检测编码: 该类根据文件的前 4 个字节(也称为字节顺序标记 (BOM))自动检测文件中使用的编码。这个功能可能不是最强大的,但总比没有好。
  8. 灵活自定义字符串比较:该类允许您根据应用程序的要求自定义字符串比较规则(区分大小写、区域性)。
  9. 支持各种加载和保存方法:该类提供了从字符串、流或文件加载 INI 文件的方法,以及将它们保存到流或文件的方法。
  10. 用于处理 INI 文件的便捷 API:该类提供了简单直观的 API,用于向 INI 文件读写值,包括支持各种数据类型。

因此,使用 IniFile 类可以高效灵活地处理 INI 文件,保留其结构和格式,并为自定义和功能扩展提供了充足的机会。

类的结构

该类存储允许您更精确地自定义文件分析过程的字段。

  1. 存储 INI 文件内容。 该类有一个私有字段 _content 来存储 INI 文件内容。
  2. 用于解析的正则表达式。 该类使用存储在 _regex 字段中的正则表达式来解析 INI 文件。
  3. 支持转义字符。 _allowEscapeChars 标志决定了 INI 文件中是否允许转义字符。
  4. 定义换行符的类型。 不同的操作系统使用不同的方法来标记一行的结束。在我们可以处理文件之前,我们必须确定文件中使用了哪种方法。_lineBreaker 字段包含用于表示 INI 文件中换行的字符串。
  5. 区域性信息。 _culture 字段包含有关用于解析的区域性的信息。
  6. 字符串比较规则。 _comparison 字段决定了如何在 INI 文件中执行字符串比较。

类方法

IniFile 类提供了方便的方法,用于将各种类型的值读写到 INI 文件中。

  1. 读取值
    • ReadStringReadStrings - 用于读取字符串值,包括字符串数组。
    • ReadObjectRead<T> - 使用 TypeConverter 读取任意类型的值。
    • ReadArray - 用于读取任意类型的值数组。
    • 读取基本数据类型的方法:ReadBooleanReadCharReadSByteReadByteReadInt16ReadUInt16ReadInt32ReadUInt32ReadInt64ReadUInt64ReadSingleReadDoubleReadDecimalReadDateTime
  2. 写入值
    • WriteStringWriteStrings - 用于写入字符串值,包括字符串数组。
    • WriteObjectWrite<T> - 使用 TypeConverter 写入任意类型的值。
    • WriteArray - 用于写入任意类型的值数组。
    • 写入基本数据类型的方法:WriteBooleanWriteCharWriteSByteWriteByteWriteInt16WriteUInt16WriteInt32WriteUInt32WriteInt64WriteUInt64WriteSingleWriteDoubleWriteDecimalWriteDateTime。这些方法允许您轻松地读写 INI 文件中的值,自动执行类型转换(使用 TypeConverter)。这简化了使用 INI 文件的工作,并使代码更具可读性和可靠性。
    •  
  3. 此外,IniFile 类还提供了便捷的方法,可以根据 INI 文件中存储的数据自动初始化对象属性。这大大简化和加快了读写 INI 文件设置的过程。ReadSettings WriteSettings 方法允许您自动读取和写入给定类型的 (包括嵌套类型) 的所有静态属性。当应用程序有许多分布在不同类别的设置时,这非常有用。ReadProperty WriteProperty 方法允许您读取和写入对象的单个属性值。这样做,它们会自动根据属性的名称和类型确定属性的节和键,从而消除了开发人员手动指定此信息的需要。因此,使用这些方法可以大大简化使用 INI 文件的工作,与手动管理设置的读写相比,它更高效且不易出错。它们还支持各种数据类型,包括数组,并提供了使用自定义类型转换器的能力。

这些方法使用 _regex 字段中存储的正则表达式来处理 INI 文件内容。该类还提供了一些用于处理正则表达式、字符串和文件系统的辅助方法。

该类提供了静态 Load 方法,用于从各种来源(字符串、流、文件)加载 INI 文件,以及 Save 方法,用于将 INI 文件内容保存到各种输出流。

IniFile 类包含一些额外的辅助方法,用于处理解析器设置、正则表达式、字符串和文件系统。

  1. GetCultureInfo:返回一个 CultureInfo 对象,该对象定义了指定 StringComparison 的字符串比较规则。
  2. GetRegexOptions:根据指定的 StringComparison 设置或清除 RegexOptions 标志,并返回修改后的值。
  3. GetComparer:返回一个基于指定 StringComparison 的 StringComparer 对象。
  4. ToEscape:使用反斜杠转义输入字符串中的特殊字符。
  5. UnHex:将十六进制数转换为 Unicode 字符。
  6. UnEscape:转换输入字符串中的所有转义字符。
  7. MoveIndexToEndOfLinePosition:在 StringBuilder 中将索引移动到当前行的末尾。
  8. InsertLine:在 StringBuilder 的指定索引处插入指定字符串,后跟指定的换行符,并更新索引。
  9. AutoDetectLineBreaker:确定指定字符串中的换行符类型("\r\n""\n" 或 "\r")。
  10. AutoDetectLineEncoding:尝试根据文件内容的前四个字节(BOM)来确定文本编码。
  11. MayBeToLower:根据指定的 StringComparison 在必要时将字符串转换为小写。
  12. IsInvalidPath:检查文件名字符串是否包含路径的无效字符。
  13. ValidateFileName:检查文件名是否有效,以及(可选)文件是否存在。
  14. GetFullPath:通过检查其有效性,返回给定文件名的完整路径。
  15. GetDeclaringPath:使用指定的目录分隔符返回指定类型的声明路径。

这些辅助方法在 IniFile 类内部使用,以确保与正则表达式、字符串、文件系统和解析器设置的正确交互。

工作原理

此类不使用集合来存储数据。相反,它使用正则表达式来解析 INI 文件内容。这使得您可以省略集合,并在编辑时保留原始文件格式。

GetSectionsGetKeysGetValueGetValuesSetValue 和 SetValues 方法中使用的遍历 INI 文件内容的通用算法如下:

  • 初始化一个正则表达式,该正则表达式将文件内容分割成节、键和值。
  • 遍历文件内容中正则表达式的所有匹配项。
  • 对于每个匹配项,检查它是节、键还是值。
  • 根据匹配项的类型,保存其信息并用于相应的方法。
  • 对于 GetValueGetValuesSetValue 和 SetValues 方法,还会另外监视当前匹配项所在的节,以便在正确的节中返回或设置值。
  • 处理所有匹配项的结果将被返回或用于修改文件内容。这种方法允许您在无需使用集合的情况下高效地处理 INI 文件内容,同时保留原始文件格式。

所有这些方法的核心看起来是这样的:

Regex regex;    // A regular expression object.
string content; // A string containing INI file data.
// ...

// Iterate over the content to find the section and key
for (Match match = regex.Match(content); match.Success; match = match.NextMatch())
{
	if (match.Groups["section"].Success)
	{
		// Handling actions for sections.
	}
	
	if (match.Groups["entry"].Success)
	{
		// Handling actions for entries.
	}
	
	// Updating content if necessary.
}

如果我们只需要获取文件中所有节的列表,这非常简单:

string section;   // String contains a section name. 
string key;       // String contains a key name. 

HashSet<string> sections = new HashSet<string>();

for (Match match = _regex.Match(Content); match.Success; match = match.NextMatch())
{
    if (match.Groups["section"].Success)
    {
        sections.Add(match.Groups["value"].Value);
    }
}

在其他需要处理键的情况下,我们首先使用额外的标志 inSection 检查我们是否在一个节中。

string section;   // String contains a section name. 
string key;       // String contains a key name. 

HashSet<string> keys = new HashSet<string>(); // A collection of unique names.
bool inSection = false; // Indicates that we are in a section.

for (Match match = _regex.Match(Content); match.Success; match = match.NextMatch())
{
    if (match.Groups["section"].Success)
    {
        inSection = match.Groups["value"].Value.Equals(section);
        continue;
    }

    if (inSection && match.Groups["entry"].Success)
    {
        string key = match.Groups["key"].Value;
        keys.Add(key);
    }
}

SetValue 和 SetValues 方法写入数据的通用算法如下:

  • 创建一个 StringBuilder 实例,用于修改 INI 文件内容。
  • 使用正则表达式遍历文件内容。
  • 如果找到一个匹配搜索键的节或条目,则:
  • 获取代表值的组。
  • 计算代表值的组的索引和长度。
  • 从 StringBuilder 中移除旧值。
  • 如果新值不为空,则将其插入 StringBuilder 中。
  • 如果在迭代后,表示值未设置的标志仍然设置,则:
  • 计算新条目应插入的索引。
  • 如果这不是全局节,并且该节尚未遇到,则将新节插入 StringBuilder 中。
  • 将具有键和值的新条目插入 StringBuilder 中。
  • 将 StringBuilder 的内容写回 IniFile 实例的内容。

通过用其索引和长度替换找到的值来更新现有键值。新值插入在相同的位置,替换之前的,保留缩进。实现相当简单:

string section;   // String contains a section name. 
string key;       // String contains a key name. 
string value;     // String contains a new value.

// Create a content editor.
StringBuilder sb = new StringBuilder(content);

for (Match match = _regex.Match(Content); match.Success; match = match.NextMatch())
{
    if (match.Groups["section"].Success)
    {
        inSection = match.Groups["value"].Value.Equals(section);
        continue;
    }

    if (inSection && match.Groups["entry"].Success)
    {
        // The match was found on the current iteration.
        if (!match.Groups["key"].Value.Equals(key)) 
            continue;

        // Value and it's start and stop position to replace.
        Group group = match.Groups["value"];
        int index = group.Index;
        int length = group.Length;

        // Remove the old value.
        sb.Remove(index, length);

        // Insert the new value in its place.
        sb.Insert(index, value);
    }
}

// Updating the content.
content = sb.ToString();

使用代码

基本操作

以下是一些使用 IniFile 类的示例。

打开文件

// Here is an example of loading a file with parsing options 
// that were explicitly specified:
IniFile ini = IniFile.Load("config.ini", Encoding.UTF8, 
StringComparison.InvariantCultureIgnoreCase, true);

// All the above parameter values ​​after the file name
// are passed in the form they are implied by default,
// So you can write the same in a shorter way:
ini = IniFile.Load("config.ini");

将参数读取到字符串变量中

string value = ini.ReadString("Section1", "Key1", "default value");

// If you want to receive a key without a section (or above all sections), 
// pass in a null or empty string as the section name:
value = ini.ReadString("", "Key0", "default value");
// - or -
value = ini.ReadString(null, "Key0", "default value");

将参数读取到整数变量中

int intValue = ini.ReadInt32("Section1", "IntKey", 42);

将字符串数组读取到新变量中

string[] values ​​= ini.ReadStrings("Section1", "ArrayKey", "default1", "default2");

使用索引器读取

string value = ini["Section1", "Key1", "default"];

读取各种类型的对象

// In this example, we use the ReadObject method of the IniFile class 
// to read the value of the CultureInfo parameter from the Settings section. 
// We pass the CultureInfo type as the desired type,
// the default value CultureInfo.InvariantCulture, 
// and an instance of CultureInfoTypeConverter as the type converter.
CultureInfo culture1 = (CultureInfo)ini.ReadObject("Settings", "Culture", 
                        typeof(CultureInfo),
                        CultureInfo.InvariantCulture, 
                        new CultureInfoTypeConverter());

// In this example, we use a generic method Read without using an optional parameter.
Uri uri = ini.Read<Uri>("Settings", "Culture");

使用索引器写入

ini["Section1", "Key1"] = "new value";

写入字符串

ini.WriteString("Section1", "Key1", "new value");

写入字符串数组

ini.WriteStrings("Section1", "ArrayKey", "value1", "value2", "value3");

使用索引器写入

ini["Section1", "Key1"] = "new value";

保存文件

ini.Save("config.ini");

初始化自定义类

首先,我们创建 Person 类:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public DateTime Birthday { get; set; }
}

现在,让我们来看一个使用我们创建的类的 ReadSettings 方法的示例。

// Create an instance of IniFile.
IniFile ini = new IniFile("person.ini");

// Reading the settings for the Person class.
Person person = new Person();
ini.ReadSettings(person);

// We display data about a person.
Console.WriteLine($"Name: {person.Name}");
Console.WriteLine($"Age: {person.Age}");
Console.WriteLine($"Birthday: {person.Birthday.ToString("yyyy-MM-dd")}");

此代码使用的 person.ini 文件内容:

[Person] 
Name=John
Age=35
Birthdyay=1989-04-25

同时,要从 INI 文件参数读取 Person 对象,您可以使用以下方法,即使用类型转换器。有必要为 Person 类创建 PersonTypeConverter

public class PersonTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, 
                                       CultureInfo culture, object value)
    {
        if (value is string str)
        {
            string[] parts = str.Split(',');
            if (parts.Length == 3)
            {
                return new Person
                {
                    Name = parts[0].Trim(),
                    Age = int.Parse(parts[1].Trim()),
                    Birthday = DateTime.Parse(parts[2].Trim())
                };
            }
        }

        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, 
                                     CultureInfo culture, 
                                     object value, 
                                     Type destinationType)
    {
        if (value is Person person)
        {
            return $"{person.Name},
                     {person.Age},
                     {person.Birthday.ToString("yyyy-MM-dd")}";
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }
}

这样,我们就可以使用自定义 TypeConverter 在 INI 文件中存储和读取 Person 对象。

var iniFile = new IniFile();
DateTime birthDay = DateTime.ParseExact(
    "25-04-1989", 
    "dd-MM-yyyy", 
    CultureInfo.InvariantCulture
);
Person person = new Person { Name = "John", Age = 35, Birthday = birthDay };
iniFile.WriteObject("Section1", "Person", person, new PersonTypeConverter());
var person = iniFile.Read<Person>("Section1", "Person", null, new PersonTypeConverter());
iniFile.Save("persons.ini:);

此代码生成的 persons.ini 文件内容:

[Section1] 
Person=John,35,1989-04-25

从示例中可以看出,IniFile 在处理各种数据类型时具有许多优点。

通过使用正则表达式且不使用集合,IniFile 可以快速读写 INI 文件数据,并保留格式。这使得在不降低性能的情况下处理大量数据成为可能。

IniFile 支持根据 INI 文件中的数据自动初始化对象属性。这简化了应用程序的设置,并消除了手动提取和分配值给属性的需要。

IniFile 提供了方便的方法来读取和写入不同类型的数据,包括标准的 .NET 类型。它还允许使用自定义类型(通过 TypeConverter),这减少了类型转换时出错的可能性。因此,IniFile 是一个强大而灵活的 INI 文件处理工具,在处理任意数据类型时提供了高效率、易用性和可扩展性。

结论

在 C# 中使用正则表达式解析 INI 文件提供了一种高效灵活的处理配置数据的方法。这种方法不仅可以正确解析内容,还可以保留原始格式,这在某些应用程序中可能至关重要。

虽然该类不使用集合,但如果您需要添加数据缓存,可以轻松修改它以使用 MatchCollection

希望本文能帮助您更好地理解和使用正则表达式来处理 INI 文件!

© . All rights reserved.