此页面将显示代码示例,这些示例将帮助您使用此解析器读取INI文件的内容。请参阅配置页面以了解如何在解析文件时更改。
INI文件结构
各个部分的INI文件const,每个定义一个唯一的键,并为每个键分配一个唯一的值。
节被声明为包含在方括号中的唯一单词。方括号内的空格将被忽略,但必须使用唯一的单词([sampleSection])定义该部分
在部分中,我们可以定义具有唯一值的键。键在同一部分中必须唯一,但在不同部分中可以具有相同的键名称。使用等号分配键(键=值)
另外,我们可以使用分号(;)定义单行注释。
因此,可以这样编写一个简单的INI文件:
[ section ]
;comment
key = value
所有代码示例均期望以下using子句:
using IniParser;
using IniParser.Model;
首先要做的是创建一个INI解析器的实例
//创建一个ini文件解析器的实例
var parser = new IniDataParser();
ini解析器只能使用字符串中的INI数据,因此,如果要解析文件或获取ini数据,则可以使用提供的一些帮助器类(FileIniParser或StreamIniParser),或者仅从任何源读取ini数据源自己作为字符串,然后使用IniDataParser.Parse方法。
// 使用FileIniDataParser实例轻松解析或持久保存ini文件。
var parser = new FileIniDataParser();
现在,我们可以使用ReadFile解析器对象中的Method获取INI数据。这将返回一个新IniData实例,其中包含从INI文件解析的所有数据:
var parser = new FileIniDataParser();
// 这将加载INI文件,读取失败中包含的数据,并解析该数据
IniData data = parser.ReadFile("TestIniFile.ini");
ini文件中的所有节都由表示SectionDataCollection,这不过是SectionData实例的集合。每个SectionData字符串都包含一个带有该部分名称的字符串,一个包含与该部分关联的注释的字符串列表以及该部分中的键列表。该列表由实例KeyDataCollection集合表示KeyData。
由于实现了DataCollection类型,IEnumerator因此可以使用for each循环来迭代数据:
//通过所有的段迭代
foreach (SectionData section in data.Sections)
{
Console.WriteLine("[" + section.Name + "]");
//遍历当前节中的所有键以打印值
foreach(KeyData key in section.Keys)
Console.WriteLine(key.Name + " = " + key.Value);
}
如果知道所需部分的名称和键,则可以直接访问数据
//此行从“ GeneralConfiguration”部分获取SectionData
KeyDataCollection keyCol = data["GeneralConfiguration"];
//此行从“generalconfiguration”部分定义的键“setupdate”获取keydata
string directValue = keyCol["setUpdate"];
//但是一口气获取值更容易:
directValue = data["GeneralConfiguration"]["setUpdate"];
解析的数据也可以轻松地修改:
data["GeneralConfiguration"]["setUpdate"] = "150";
您可以通过编程方式添加或删除部分和/或键/值对:
var parser = new FileIniDataParser();
IniData data = parser.ReadFile("TestIniFile.ini");
//添加一个新部分和一些键
data.Sections.AddSection("newSection");
data["newSection"].AddKey("newKey1", "value1");
data["newSection"].AddKey("newKey2", "value5");
//删除最后一个键
data["newSection"].RemoveKey("newKey2");
//从文件中删除“Users”部分以及与之关联的所有键和注释
data.Sections.RemoveSection("Users");
如果您对已解析的数据进行了修改,或者创建了一个新IniData实例并填充了它,则可能希望将数据保存到文件中。为此,只需使用FileIniDataParser实例中的“ SaveFile”方法:
var parser = new FileIniDataParser();
//获取数据
IniData parsedINIDataToBeSaved;
//保存文件
parser.WriteFile("newINIfile.ini", parsedINIDataToBeSaved);
您也可以使用IniData.ToString()方法创建包含ini文件内容的字符串。
IniData data = new IniData();
data["Section1"]["key1"] = "value1";
Console.WriteLine(data.ToString());
该示例中使用的INI文件包含以下信息:
;This section provides the general configuration of the application
[GeneralConfiguration]
;Update rate in msecs
setUpdate = 100
;Maximum errors before quitting
setMaxErrors = 2
[UI]
fullscreen = false
;Users allowed to access the system
;format: user = pass
[Users]
ricky = rickypass
patty = pattypass
由于INI格式没有标准化,因此Ini Parser 2.0版引入了一种更简单的方法来定制INI文件的解析方式,从而提供了一种处理所有不同格式变化的简便方法。
使用IniParserConfiguration对象,您可以重新定义解析ini文件时解析器将如何处理特殊项目。例如,您可以重新定义用作注释的字符,而不是使用字符’;’。(默认),您可以设置以’#'字符开头的行为注释。
您还可以定义解析器应如何处理错误(例如,抛出异常或仅返回null值),或者在解析具有“奇怪”格式的文件时应具有的自由度或保守度。
创建的实例时,IniDataParser您可以传递配置对象。配置对象跟随。IIniParserConfiguration接口。如果您不提供默认实例,则将使用默认实例。
您可以使用IniDataParser实例中的Configuration属性来访问和修改解析器的配置。有关示例,请参见parse_ini_string_with_custom_configuration测试。
如果您发现自己在许多地方都使用了自定义配置,则最好使用所需的行为来创建自定义配置对象。只需创建一个派生类BaseIniParserConfiguration并在构造函数中设置自定义属性的值即可。这是DefaultIniParserConfiguration实际使用的方法。
这是IIniParserConfiguration接口规范中定义的配置选项的列表:
类型 | 描述 | 名称 |
---|---|---|
bool | AllowCreateSectionsOnFly | 如果为true,如果您尝试将键添加到不存在的部分,则该部分将自动动态创建,而不会引发异常。默认为false。 |
bool | AllowDuplicateKeys | 如果在某节中找到重复的键,这是false解析器将因错误而停止。如果它是true重复键的值,则将是分配给键的最后一个值。默认为false。 |
bool | AllowDuplicateSections | 如果设置为,false并且找到重复的部分,则解析器将停止并显示错误。如果设置为true,则文件中允许使用重复的节,但是将仅SectionData在IniData.Sections集合中创建一个元素,从而有效地合并相同名称的重复节中的所有键。默认为false。 |
bool | AllowKeysWithoutSection | 允许文件中有不属于任何部分的键。即允许在定义部分之前定义键。如果设置为,false并且定义了没有节的键,则解析器将因错误而停止。默认为true。 |
string | AssigmentSpacer | 设置KeyValuesAssignmentString之前和之后的字符串。默认为字符串“” |
Regex | CommentRegex | 用于匹配注释字符串的正则表达式 |
char | CommentString | 设置将定义注释开头的字符串。注释从注释字符到行尾。默认为“#” |
char | KeyValueAssigmentString | 设置将值的分配与键分开的字符串。默认为“ =” |
bool | OverrideDuplicateKeys | 仅适用,如果AllowDuplicateKeys是true。如果设置为true当解析器发现重复的键时,它将覆盖先前的值,因此该键将始终包含文件中读取的最后一个键的值。如果设置为false第一个读取的值,则保留该键,因此该键将始终包含文件中读取的第一个键的值。默认为false。 |
char | SectionEndString | 设置定义节名结尾的字符串。默认为“]” |
Regexr | Regex | 用于匹配部分字符串的正则表达式 |
char | SectionStartString | 设置定义节名称开头的字符串。默认为“ [” |
bool | SkipInvalidLines | 如果设置为true,则当解析器发现无效行时,它只会跳过该行,而不是ParseException在解析时抛出a 或返回null(如果由于将属性ThrowExceptionsOnError设置为false,则禁用了异常)。默认为false |
bool | ThrowExceptionsOnError | 如果true发现错误,解析器将引发异常。如果false解析器将仅停止执行并返回一个null值作为结果。默认为true。 |
string | NewLineStr | 用作NewLine的字符串。仅在从IniData结构创建ini字符串时使用,使用IIniDataFormatter。例如,这允许在Windows上使用类unix的结尾字符串创建ini文件。默认值是用于执行此库的系统的正确的换行符/字符串。 |
如果需要细粒度的自定义进行解析,则可以从中创建派生类IniDataParser并覆盖某些方法。请参见修改解析器页面
如果您需要对解析算法进行更细粒度的自定义,则可以从中创建派生类IniDataParser并覆盖控制解析操作的方法(例如,检查行是否为注释,段或键值的方法)作业等)
请注意,如果您只想更改解析的一些小方面(例如更改用于定义注释的字符),则可以为解析器创建自定义配置来节省时间。请参阅配置解析器行为页面以获取更多信息。
解析算法中的所有步骤都是使用受保护的方法执行的,因此可以在派生类中对其进行修改。这是[模板方法模式]的特例,其中提供了模板方法的默认实现。
这是可以在派生类中进行更改以修改解析器的方法的列表,该解析器的算法通过以下步骤工作:
/// <summary>
/// 处理一行并解析在该行中找到的数据(可能有或可能没有注释的节或键/值对)
/// </summary>
/// <param name="currentLine">The string with the line to process</param>
protected void ProcessLine(string currentLine, IniData currentIniData)
该方法首先提取注释,如果行
/// <summary>
/// 检查给定字符串是否包含注释。
/// </summary>
/// <param name="line">
/// 要检查的字符串。
/// </param>
/// <returns>
/// <c>true</c> 如果s中的任何子字符串是注释,则<c>false</c>否则。
/// </returns>
protected bool LineContainsAComment(string line)
/// <summary>
/// 从字符串中移除注释(如果存在),并返回不带注释子字符串的字符串。
/// </summary>
/// <param name="line">
/// 要从中删除注释的字符串。
/// </param>
/// <returns>
/// The string s without comments.
/// </returns>
protected string ExtractComment(string line)
/// <summary>
/// 检查给定的字符串是否表示节定界符。
/// </summary>
/// <param name="line">
/// 要检查的字符串。
/// </param>
/// <returns>
/// < c > true </ c >如果字符串表示一个节,否则返回< c > false </ c >。
/// </returns>
protected bool LineMatchesASection(string line)
/// <summary>
/// 检查给定的字符串是否表示键/值对。
/// </summary>
/// <param name="line">
/// 要检查的字符串。
/// </param>
/// <returns>
/// <c>true</c> 字符串是否表示一个键/值对, <c>false</c> 否则
/// </returns>
protected bool LineMatchesAKeyValuePair(string line)
/// <summary>
/// 处理 包含ini节的字符串。
/// </summary>
/// <param name="line">
/// 要处理的字符串
/// </param>
protected void ProcessSection(string line, IniData currentIniData)
/// <summary>
/// 处理包含ini键/值对的字符串。
/// </summary>
/// <param name="line">
/// 要处理的字符串
/// </param>
protected void ProcessKeyValuePair(string line, IniData currentIniData)
/// <summary>
/// 提取包含键/值对的字符串的键部分
/// </summary>
/// <param name="s">
/// 要处理的字符串,其中包含键/值对
/// </param>
/// <returns>
/// 所提取键的名称。
/// </returns>
protected string ExtractKey(string s)
/// <summary>
/// 提取包含键/值对的字符串的值部分
/// </summary>
/// <param name="s">
/// 要处理的字符串,其中包含键/值对
/// </param>
/// <returns>
/// 提取值的名称。
/// </returns>
protected string ExtractValue(string s)