在C#中读取ini文件

4

我正在尝试读取一个具有以下格式的ini文件:

SETTING=VALUE 
SETTING2=VALUE2

我目前有以下代码:

我目前有以下代码:

string cache = sr.ReadToEnd();                    
string[] splitCache = cache.Split(new string[] {"\n", "\r\n"}, StringSplitOptions.RemoveEmptyEntries);

这给了我一份设置清单,但我想要的是将其读入字典中。我的问题是,是否有一种方法可以在不迭代整个数组并手动填充字典的情况下完成此操作?


为什么不直接使用foreach循环? - Matt
我可以这样做 - 但问题是我能否在不迭代数组的情况下完成它。 - Paul Michaels
1
如果你想跳过繁琐的工作,http://www.codeproject.com/KB/cs/readwritexmlini.aspx是一个很好的INI读取器。 - Chris S
6个回答

8

你可以使用LINQ,如下所示:

Dictionary<string, string> ini = (from entry in splitCache
                                  let key = entry.Substring(0, entry.FirstIndexOf("="))
                                  let value = entry.Substring(entry.FirstIndexOf("="))
                                  select new { key, value }).ToDictionary(e => e.key, e => e.value);

正如Binary Worrier在评论中指出的那样,这种方法与其他答案建议的简单循环相比没有任何优势。

编辑:上面代码块的一个更短的版本如下:

Dictionary<string, string> ini = splitCache.ToDictionary(
                                   entry => entry.Substring(0, entry.FirstIndexOf("="),
                                   entry => entry.Substring(entry.FirstIndexOf("="));

1
@pm_2. 请注意,这只是在一些相当丑陋的linq下隐藏了一个非常简单的循环。虽然按照要求回答问题会得到+1,但我更喜欢使用循环。 - Binary Worrier
除了明显的可读性问题,使用这种方法还有其他什么缺点吗? - Paul Michaels
@pm_2:你不能使用调试器逐步执行LINQ表达式。除此之外,我不知道还有什么其他方法。 - Jens
1
有一个好处。编译器/运行时更有可能自动化地并行LINQ编写的代码,以便可以在多个CPU上运行,而不是循环。 - Scott Langham

7
迭代有什么问题吗?
var lines = File.ReadAllLines("pathtoyourfile.ini");
var dict = new Dictionary<string, string>();

foreach(var s in lines)
{
     var split = s.Split("=");
     dict.Add(split[0], split[1]);
}

3

INI文件有些棘手,所以我不建议自己编写。我编写了Nini,这是一个配置库,包含了一个非常快速的解析器。

示例INI文件:

; This is a comment
[My Section]
key 1 = value 1
key 2 = value 2

[Pets]
dog = rover
cat = muffy

相同的C#代码:

// Load the file
IniDocument doc = new IniDocument ("test.ini");

// Print the data from the keys
Console.WriteLine ("Key 1: " + doc.Get ("My Section", "key 1"));
Console.WriteLine ("Key 2: " + doc.Get ("Pets", "dog"));

// Create a new section
doc.SetSection ("Movies");

// Set new values in the section
doc.SetKey ("Movies", "horror", "Scream");
doc.SetKey ("Movies", "comedy", "Dumb and Dumber");

// Remove a section or values from a section
doc.RemoveSection ("My Section");
doc.RemoveKey ("Pets", "dog");

// Save the changes
doc.Save("test.ini");

1
不错,对于所有非平凡使用 ini 文件的情况都很有用。 - Renaud Bompuis

3

实际上,Windows API中有一个用于读取/写入INI文件的API,它位于kernel32.dll库中;可以参考这篇CodeProject文章来了解示例。


2

试试这样

[DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileString")]

public static extern int GetPrivateProfileString(string SectionName, string KeyName, string Default, StringBuilder Return_StringBuilder_Name, int Size, string FileName);

而且这个函数的调用方式是这样的:
GetPrivateProfileString(Section_Name, "SETTING", "0", StringBuilder_Name, 10, "filename.ini");

可以从 StringBuilder_Name 访问值。


0
为什么不将文件读取为单独的行,然后循环遍历它们,在第一个=处进行分割?
var dict = new Dictionary<string,string>();
foreach (var line in File.ReadAllLines(filename)) {
  var parts = line.Split('=', 2); // Maximum of 2 parts, so '=' in value ignored.
  dict.Add(parts[0], parts[1]);
}

在.NET 4中,将ReadAllLines替换为ReadLines,以避免创建数组,ReadLines返回IEnumerable<String>并惰性读取文件。

1
难道不应该是dict.Add(parts[0], parts[1]);吗? - ZombieSheep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接