我正在对读取CSV文件的不同方法进行一些基准测试,并发现了一个“奇怪”的问题。问题是当我在控制台应用程序中使用此方法时:
var lines = File.ReadAllLines(fileName); // OutOfMemoryException
foreach (var line in lines)
{
//doing stuff
}
我得到一个OutOfMemoryException,但是当我在WPF项目中使用相同的方法时,它工作正常。 我正在测试这个文件是730MB,我知道不要在更大的CSV文件上使用ReadAllLines,但为什么这个方法在WPF应用程序中有效但在控制台应用程序中却无效?
答案 0 :(得分:5)
您正在使用32位进程并遭受地址空间碎片。这意味着运行时无法分配足够的连续内存,尽管总共可以释放足够的内存。 WPF可能只是有更好的内存布局。
将项目更改为64位。
或者,使用File.ReadLines
流式传输文件。
答案 1 :(得分:3)
我怀疑你的WPF应用程序是在任何CPU上编译的,你在x32目标CPU上控制应用程序。如果在x64计算机上运行应用程序,则与x32编译的控制台应用程序(大约1.5 GB)相比,WPF应用程序可以使用更多内存。
另外我建议改变你的方法,如果可能的话,不要一次处理整个文件。
答案 2 :(得分:0)
我不会直接回答你的问题,但我认为指出OutOfMemoryException
经常表明你的程序存在太大的记忆压力是非常重要的。 ,或者没有以非常好的方式使用可用资源。
在您的情况下,您通过调用File.ReadAllLines
有效地将整个文件缓存在内存中。但是,这可能根本就没有必要,因为之后,您将逐行处理它。也就是说,在任何一个时刻只在内存中只有一行文本就足够了:
正如this answer所述,您可以使用File.ReadLines
逐行流式传输文件。
如果您的目标是.NET 4之前的.NET Framework版本,那么该方法将无法使用。您可以将其替换为您自己的实现,例如:
// using System.IO;
static IEnumerable<string> ReadLines(string filePath)
{
using (var input = File.OpenText(filePath))
{
while (!input.EndOfStream)
{
string line = input.ReadLine();
yield return line;
}
}
}