如何提高IEnumerable <t> File.ReadLines()中访问行的性能

时间:2017-01-10 21:26:48

标签: c#

我正在使用File.ReadLines方法加载文件(文件可能变得非常大,所以我使用它而不是ReadAllLines)

我需要访问每一行并对其执行操作。所以我的代码就像这样

IEnumerable<String> lines = File.ReadLines("c:\myfile.txt", new UTF8Encoding());

StringBuilder sb = new StringBuilder();

int totalLines = lines.Count();  //used for progress calculation

//use for instead of foreach here - easier to know the line I'm on for progress percent complete calculation
for(int i = 0; i < totalLines; i++){

    //for example get the line and do something
    sb.Append(lines.ElementAt(i) + "\r\n");

    //get the line again using ElementAt(i) and do something else
    //...ElementAt(I)...
}

因此,我每次访问ElementAt(i)时都会遇到瓶颈,因为它必须遍历整个IEmumerable才能到达位置i。

有没有办法继续使用File.ReadLines,但以某种方式改进了这个?

编辑 - 我在开始时计算的原因是我可以计算完成的进度以显示给用户。这就是为什么我删除foreach以支持for。

2 个答案:

答案 0 :(得分:2)

如何使用foreach?它旨在处理这种情况。

IEnumerable<String> lines = File.ReadLines("c:\myfile.txt", new UTF8Encoding());

StringBuilder sb = new StringBuilder();

string previousLine = null;
int lineCounter = 0;
int totalLines = lines.Count();

foreach (string line in lines) {

    // show progress
    float done = ++lineCounter/totalLines;
    Debug.WriteLine($"{done*100:0.00}% complete");

    //get the line and do something
    sb.AppendLine(line);

    //do something else, like look at the previous line to compare
    if (line == previousLine) {
        Debug.WriteLine($"Line {lineCounter} is the same as the previous line.");
    }

    previousLine = line;
}

答案 1 :(得分:0)

当然,您可以使用foreach代替for循环,因此您无需返回并通过其索引引用该行:

foreach (string line in lines)
{
    sb.AppendLine(line);
}

您也不再需要int totalLines = lines.Count();行,因为您不需要计算任何内容(除非您使用的地方没有显示)。