我在以下 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”,“”,...应该用空代替)。目前我正在使用带有 incr 变量的 foreach 来更新 foreach 内的项目。
我想知道 linq 或 lambda 会更快,但我在这些领域还很陌生。
最佳答案
首先,不要在更改集合时使用foreach
,这不是一个好习惯,尤其是当您已经使用了计数器变量时。
这个循环可以使用 Parallel.For
以这种方式变成多线程:
代码使用正常:
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;
}
}
});
但我认为这不值得。你决定。这些类型的操作不适合并行化,因为它们计算时间太少,开销太大。
关于c# - foreach 循环内更快的数据检查和更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48019740/