我需要将大量未分类的数据(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);
}
}
答案 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()