内存不足异常

3

我有一个类类型的列表,其中包含(字符串,字符串,字符串,字符串,整数,日期时间,日期时间)。这些字符串的总字符数相加等于28。

我读取文件来填充列表,最终列表中将包含19,000,000(一千九百万)个这样的对象。

我像这样读取文件并添加到列表中:

public void ReadDocGrabValues(string fileREAD)
{
    using (var file = new StreamReader(fileREAD))
    {
        var j = file.ReadLine();

        while (j != null)
        {
            mylist.Add(new IDandAGE(j.Substring(0, 15), j.Substring(16, 1), j.Substring(18, 6), j.Substring(25, 6), 0, DateTime.Today, DateTime.Today));
            j = file.ReadLine();
        }
    }
}

这应该不是问题。然后我遍历整个列表,从两个字符串中计算出DateTime对象。

public void ConvertYOBDOI()
{
    foreach (IDandAGE x in mylist)
    {
        string IssueDate = (x.StringDOD.Substring(0,4) + "-" + x.StringDOD.Substring(4,2) + "-01");
        string BirthDate = (x.StringYOB.Substring(0,4) + "-" + x.StringYOB.Substring(4,2) + "-01");
        x.DeathDate= DateTime.Parse(DeathDate);
        x.YearOfBirth = DateTime.Parse(BirthDate);

     }
}

我会循环查找整个列表,计算年龄值。
public void DateCalc()
{
    foreach (IDandAGE w in mylist)
    {
        w.Age = w.DateOfDeath.Year - w.YearOfBirth.Year;
        if (w.YearOfBirth > w.DateOfDeath.AddYears(-w.Age)) w.Age--;

    }
}

最后,我将想要从列表中提取的值写入文件。
public void CreateAgeFile()
{
   StreamWriter a = new StreamWriter(@"C:\GetAgeTest.txt");

    foreach (IDandAGE x in mylist)
    {
       String f = (x.ID + "," + x.Gender + "," + x.StringYOB + "," + x.StringDOD + "," + x.Age + ",NULL,NULL,NULL");
        a.WriteLine(f);
    }
    a.Close();

}

我刚开始学习编程,对于代码效率低下/糟糕的情况以及无法回答自己的问题提前道歉。

我猜可能有多种原因导致它给我抛出这个异常,因为我要遍历列表好几次。

欢迎任何帮助或建议。

谢谢。


你在哪里出现了错误? - Paul Michaels
7
你需要在内存中同时保存19M条记录(mylist.Add())的原因是什么?尝试直接将数据流式传输到文件中。 - Caramiriel
我没有展示所有的代码,因为这并不是必要的。我的程序在较小的列表大小下运行良好。public List<IDandAGE> mylist = new List<IDandAGE>(); 在类中。 - Mitchell
1
@Mitchell 关于“列表不完整”的问题 - 是的,“迭代器块”(又称 yield return)非常适合这种情况;在这里,没有列表 - 只有一个状态机。 - Marc Gravell
1
作为伪代码,在第一个循环之前,还要打开StreamWriter,在读取一行后构建类实例,然后在其上执行ConvertYOBDOIDateCalc的代码。现在您已经准备好写入StreamWriter了。@MarcGravell的答案也是开始这种方法的好方法。 - Steve
显示剩余6条评论
1个回答

7

如果您正在访问19M 条记录,那么是的:您至少需要考虑内存。目前您将它们都存储在列表中,因此它们无法被收集。如果您使用的是32位(或启用了prefer-32-bit),那么这将是紧张的。更好的想法可能是使用迭代器块,这样您就不需要一次性将它们全部加载到内存中:

public IEnumerable<IDandAGE> ReadDocGrabValues(string fileREAD)
{
    foreach(string j in File.ReadLines(fileREAD))
    {
        yield return new IDandAGE(j.Substring(0, 15), j.Substring(16, 1),
            j.Substring(18, 6), j.Substring(25, 6), 0,
            DateTime.Today, DateTime.Today);
    }
}
...
foreach (IDandAGE w in ReadDocGrabValues(path))
{
    // do per-item processing
}

谢谢,非常有帮助。 - Mitchell

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