我正在以下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 ...
}
Run Code Online (Sandbox Code Playgroud)
代码工作正常,但由于巨大的csv文件(500,000,000行和数百列),它非常慢.有没有更快的方法来检查数据(如果它是"NA","",......应该被替换为null).目前我正在使用带有incr变量的foreach来更新foreach中的项目.
我想知道linq或lambda会更快但我在这些方面很新.
首先,不要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 ...
}
Run Code Online (Sandbox Code Playgroud)
代码使用 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 ...
}
Run Code Online (Sandbox Code Playgroud)
编辑
我们可以从另一个侧面接近,但我不建议这样做,因为这需要一个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;
}
}
});
Run Code Online (Sandbox Code Playgroud)
但我不认为这是值得的.你决定.这些类型的操作在并行化方面效果不佳,因为它们只需要很少的时间进行计算,而且开销太大.