Cra*_*g W 6 .net csv split out-of-memory
我正在使用C#读取~120 MB纯文本CSV文件.最初我通过逐行读取来进行解析,但最近确定首先将整个文件内容读入内存的速度要快几倍.解析已经非常慢了,因为CSV在引号中嵌入了逗号,这意味着我必须使用正则表达式拆分.这是我发现的唯一可靠的工作方式:
string[] fields = Regex.Split(line,
@",(?!(?<=(?:^|,)\s*\x22(?:[^\x22]|\x22\x22|\\\x22)*,)
(?:[^\x22]|\x22\x22|\\\x22)*\x22\s*(?:,|$))");
// from http://regexlib.com/REDetails.aspx?regexp_id=621
Run Code Online (Sandbox Code Playgroud)
为了在将整个内容读入内存后进行解析,我在换行符上进行字符串拆分以获得包含每一行的数组.但是,当我在120 MB文件上执行此操作时,我得到了一个System.OutOfMemoryException
.当我的计算机有4 GB RAM时,为什么内存耗尽?有没有更好的方法来快速解析复杂的CSV?
基本上任何大小的分配都可以获得OutOfMemoryException.当你分配一块内存时,你真的要求连续的内存满足所需的大小.如果无法兑现,您将看到OutOfMemoryException.
您还应该知道,除非您运行64位Windows,否则您的4 GB RAM将分为2 GB内核空间和2 GB用户空间,因此您的.NET应用程序无法访问超过2 GB的默认值.
在.NET中进行字符串操作时,由于.NET字符串是不可变的,因此存在创建大量临时字符串的风险.因此,您可能会看到内存使用率急剧上升.
如果您将整个文件读入字符串,则应该使用StringReader.
StringReader reader = new StringReader(fileContents);
string line;
while ((line = reader.ReadLine()) != null) {
// Process line
}
Run Code Online (Sandbox Code Playgroud)
这应该与从文件中流式传输相同,区别在于内容已经在内存中.
测试后编辑
尝试使用140MB文件进行上述处理,其中处理包括使用line.Length递增长度变量.这在我的电脑上花了大约1.6秒.在此之后我尝试了以下内容:
System.IO.StreamReader reader = new StreamReader("D:\\test.txt");
long length = 0;
string line;
while ((line = reader.ReadLine()) != null)
length += line.Length;
Run Code Online (Sandbox Code Playgroud)
结果是大约1秒钟.
当然,您的里程可能会有所不同,特别是如果您正在从网络驱动器读取数据,或者您的处理需要足够长的时间才能让硬盘驱动器寻找其他地方 但是如果你使用FileStream来读取文件而你没有缓冲.StreamReader提供缓冲,大大增强了读取.
归档时间: |
|
查看次数: |
8919 次 |
最近记录: |