【问题标题】:Index was outside the bounds of the array on a Dictionary索引超出了字典上的数组范围
【发布时间】:2016-05-01 08:58:16
【问题描述】:

我有一个应用程序可以加载格式为key:value 的文件,然后将其添加到Dictionary。这适用于小文件,但是当我尝试加载一个有 65,000 行的文件时,它不起作用并在Dictionary.TryAdd() 上抛出Index was outside the bounds of the array.

我为 64 位架构编译我的应用程序,我还在 app.config 中设置了 <gcAllowVeryLargeObjects enabled="true" />

private void LoadFile()
{
    ConcurrentDictionary<string, string> Dict = new ConcurrentDictionary<string, string>();

    OpenFileDialog dlgFile = new OpenFileDialog();
    dlgFile.Filter = "All Files (*.*)|*.*";
    dlgFile.FilterIndex = 1;

    if (dlgFile.ShowDialog() == DialogResult.OK)
    {
        foreach (string line in File.ReadLines(dlgFile.FileName))
        {
            // Index was outside the bounds of the array.
            Dict.TryAdd(line.Split(':')[0], line.Split(':')[1]);
        }
    }
}

【问题讨论】:

  • 我认为问题出在数组索引上。你确定所有的“行”都符合要求的格式,也就是可以用':'分割吗?
  • @Daniel Leszen 是的,他们是
  • 我建议你再检查一次。抛出异常时,将鼠标悬停在line 上以查看失败的值是什么。很可能它不包含: - 如果您确定它们都包含,那么它有时是最后(空)行。
  • @J.Ivanovic 通用的Dictionary 类没有TryAdd() 方法——你使用的是哪个类?
  • 如何跳过空行?

标签: c# file dictionary


【解决方案1】:

这几乎可以肯定是因为您的其中一行不包含 :,因此对生成的拆分 string 数组的索引将失败,因为它没有 2 个部分。

您可以像这样跳过没有两个部分的行:

foreach (string line in File.ReadLines(dlgFile.FileName))
{
    var parts = line.Split(':');

    if (parts.Length == 2)
    {
         var key = parts[0];
         var value = parts[1];
         Dict.TryAdd(key, value);
    }
    else
    {
         // log that line was ignored
    }
}

顺便说一句,除非您具有并发访问权限,否则无需使用ConcurrentDictionary。您的应用程序中可能有其他地方,但您显示的代码中没有。

【讨论】:

  • 正如我在另一个答案中评论的那样,我现在遇到了另一个问题。 The CLR has been unable to transition from COM context 0xb40a9278 to COM context 0xb40a93a0 for 60 seconds.
  • 点击继续并继续等待。这可能只是需要很长时间,这可能是在 UI 线程上不这样做的一个论据。
  • BackgroundWorker 可能吗?
  • @J.Ivanovic 这是一种选择,是的。
【解决方案2】:

请尝试将 foreach 正文修改为以下代码段:

        var parts = line.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
        if (parts.Length > 1)
        {
            Dict.TryAdd(parts[0], parts[1]);
        }
        else
        {
            // ERROR logging
        }

删除空条目不是必需的,但它确保您不会将空键或值添加到字典中。我还建议确保字典不包含相同的键。

【讨论】:

  • 这解决了我的问题,但又导致了另一个问题。 The CLR has been unable to transition from COM context 0xb40a9278 to COM context 0xb40a93a0 for 60 seconds.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-19
  • 1970-01-01
相关资源
最近更新 更多