我在以下while语句中逐行读取StreamReader中的数据。
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(sep);
int incr = 0;
foreach (var item in rows)
{
if (item == "NA" | item == "" | item == "NULL" | string.IsNullOrEmpty(item) | string.IsNullOrWhiteSpace(item))
{
rows[incr] = null;
}
++incr;
}
// another logic ...
}
代码工作正常,但由于巨大的csv文件(500,000,000行和数百列),它非常慢。有没有更快的方法来检查数据(如果它是" NA","",......应该被替换为null)。目前我使用带有incr变量的foreach来更新foreach中的项目。
我想知道linq或lambda会更快但我在这些方面都很新。
答案 0 :(得分:5)
首先,在更改集合时不要使用foreach
,这不是一个好习惯,特别是当你已经使用了计数器变量时。
可以使用Parallel.For
这种方式使这个循环成为多线程:
使用normal的代码:
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(sep);
for (int i = 0; i < rows.Length; i++)
{
//I simplified your checks, this is safer and simplier.
if (string.IsNullOrWhiteSpace(rows[i]) || rows[i] == "NA" || rows[i] == "NULL")
{
rows[i] = null;
}
}
// another logic ...
}
使用Parallel.For
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(sep);
Parallel.For(0, rows.Length, i =>
{
if (string.IsNullOrWhiteSpace(rows[i]) || rows[i] == "NA" || rows[i] == "NULL")
{
rows[i] = null;
}
});
// another logic ...
}
修改强>
我们可以从另一方面接受这个,但我不建议这样做,因为这需要一个 LOT 的RAM,因为它必须将整个文件读入内存。
string[] lines = File.ReadAllLines("test.txt");
Parallel.For(0, lines.Length, x =>
{
string[] rows = lines[x].Split(sep);
for (int i = 0; i < rows.Length; i++)
{
if (string.IsNullOrWhiteSpace(rows[i]) || rows[i] == "NA" || rows[i] == "NULL")
{
rows[i] = null;
}
}
});
但我不认为这是值得的。你决定。这些类型的操作在并行化方面效果不佳,因为它们只需要很少的时间来计算,而且开销太大了。