尝试将大量数据写入文件的内存不足异常

时间:2014-09-16 15:36:34

标签: c# .net

我需要将大量未分类的数据(50000000个数字)写入文件。在运行时,我得到一个OutOfMemoryException。如何解决?

private void backgroundWorkerGenNum_DoWork(object sender, DoWorkEventArgs e)
{
    int numLimit = 50000000;
    Random randomize = new Random();
    List<string> strNums = new List<string>();

    var array = Enumerable.Range(1, numLimit).ToArray();
    array = array.OrderBy(n => Guid.NewGuid()).ToArray();
    StreamWriter file = new StreamWriter("numbers.txt");
    int i = 0;
    foreach(int element in array)
    {
        file.WriteLine(element);
        ++i;
        backgroundWorkerGenNum.ReportProgress(i);
    }
}

3 个答案:

答案 0 :(得分:4)

首先,你可以像这样洗牌你的数组:

public static class ArrayExtender
{
    public static void Shuffle<T>(this T[] a)
    {
        Random rand = new Random();
        for (int i = a.Length - 1; i > 0; i--)
        {
            int j = rand.Next(0, i + 1);
            T tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }
    }
}

好吧,现在我们可以生成随机数据:

    private void backgroundWorkerGenNum_DoWork(object sender, DoWorkEventArgs e)
    {
        int numLimit = 50000000;

        var array = Enumerable.Range(1, numLimit).ToArray();
        array.Shuffle();
        int i = 0;
        using(StreamWriter file = new StreamWriter("numbers.txt"))
           foreach (int element in array)
           {
               file.WriteLine(element);
               ++i;
               backgroundWorkerGenNum.ReportProgress(i);
           }
    }

答案 1 :(得分:1)

这是一种非常低效的随机化数字集合的方法:

array = array.OrderBy(n => Guid.NewGuid()).ToArray();

您生成的每个新Guid需要16个字节+几个字节的开销才能存储。

您有5 * 10 ^ 7个号码,您可以通过滥用OrderBy方法进行随机化。

OrderBy在内部将尝试使用您提供的密钥对集合进行排序,这需要它为数据和密钥分配内存。假设Order By将生成的密钥与每个元素一起存储,这将需要内存中超过1GB的空间。

答案 2 :(得分:1)

考虑使用像这样的shuffle方法

private void Shuffle(int[] data)
{
    var random = new Random();

    int n = data.Length;
    for (int i = 0; i < n; i++)
    {
        int idx = random.Next(i, n);

        int x = data[i];
        data[i] = data[idx];
        data[idx] = x;
    } 
}

而不是array.OrderBy(n => Guid.NewGuid()).ToArray()