【问题标题】:Reading ini file in C#C#读取ini文件
【发布时间】:2010-05-12 09:41:43
【问题描述】:

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

SETTING=VALUE 
SETTING2=VALUE2

我目前有以下代码:

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

这给了我一个设置列表,但是,我想做的是将其读入字典。我的问题是,有没有办法在不遍历整个数组并手动填充字典的情况下做到这一点?

【问题讨论】:

  • 为什么不直接使用 foreach 循环?
  • 我可以 - 但问题是我可以在不遍历数组的情况下做到这一点。
  • codeproject.com/KB/cs/readwritexmlini.aspx 是一个很好的 INI 阅读器,如果你想跳过驴工作

标签: c# arrays string


【解决方案1】:

嗯,你可以使用 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 在 cmets 中指出的那样,与其他答案建议的简单循环相比,这种方法没有任何优势。

编辑:上述块的较短版本是

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

【讨论】:

  • @pm_2。请注意,这只是在一些相当丑陋的 linq 下隐藏了一个非常简单的循环。 +1 按要求回答问题,但我更喜欢循环。
  • 除了明显的可读性问题,使用这种方法还有其他缺点吗?
  • @pm_2:您无法使用调试器单步执行 LINQ 表达式。除此之外,我什么都不知道。
  • 有一个好处。编译器/运行时更有可能自动并行化 LINQ 编写的代码,以便它可以在多个 CPU 上运行,而不是循环。
【解决方案2】:

迭代有什么问题?

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】:

    kernel32.dll 中实际上有一个用于读取/写入 INI 文件的 Windows API;示例见this CodeProject article

    【讨论】:

      【解决方案4】:

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

      示例 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");
      

      【讨论】:

      • 很好,而且对于所有非平凡的 ini 文件使用肯定有用。
      【解决方案5】:

      这样试试

      [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访问。

      【讨论】:

        【解决方案6】:

        为什么不将文件作为单独的行读取,然后在第一个 = 拆分它们循环?

        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&lt;String&gt; 并延迟读取文件。)

        【讨论】:

        • 应该是dict.Add(parts[0], parts[1]);,不是吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-18
        • 2015-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-13
        • 2021-02-14
        相关资源
        最近更新 更多