使用 C# 在大文本文件中过滤所有以特殊字符结尾的电子邮件的更快方法

the faster way to filter all emails end with a special caractere in a big text file using C#

我想要一种更快的方法来使用 c#

过滤大文本文件(超过 200MB)中所有以特殊字符结尾的电子邮件
var lines = File.ReadAllLines(file path);

foreach(var line in lines)
{
  if (line.EndsWith(myWord))
  {
    outputEmails.Text += line + Environment.NewLine;
  }
}

这段代码实现我的目标很慢。

使用File.ReadLines:

foreach (var line in File.ReadLines("file path"))
{
    if (line.EndsWith(myWord))
    {
        outputEmails.Text += line + Environment.NewLine;
    }
}

它在内部使用 StreamReader,因此您无需在读取之前将整个文件加载到内存中。


memory mapped files 可以实现更好的性能。这可以在读取文件内容时节省额外的内存复制操作。

string line;
var stringBuilder = new StringBuilder();
using (var memoryMappedFile = System.IO.MemoryMappedFiles.MemoryMappedFile.CreateFromFile(@"D:\Temp\test.txt"))
using (var viewStream = memoryMappedFile.CreateViewStream())
using (var streamReader = new StreamReader(viewStream))
{
    while ((line = streamReader.ReadLine()) != null)
        if (line.EndsWith(myWord))
            stringBuilder.AppendLine(line);
}
outputEmails.Text = stringBuilder.ToString();

是的,正如其他答案所说,使用 StringBuilder 而不是原始字符串连接也会使代码更快,尤其是当许多行匹配过滤条件时。

如果您想优化某些东西,您应该使用基准测试。 但它应该工作得更快:

        string line;
        var result = new StringBuilder();
        using (var reader = new StreamReader(fileName))
        {
            while ((line = reader.ReadLine()) != null)
            {
                if (line.EndsWith(myWord))
                    result.AppendLine(line);
            }
        }
        outputEmails.Text = result.ToString();

这里的好处:

1) 使用 StreamReader 逐行读取文件而不是一次读取所有内容。在这种情况下,您可以减少内存消耗。此外,您可以使用 ReadLineAsync 使代码异步。

2) 使用 StringBuilder,您不会在每个连接中创建新的字符串实例。

希望对您有所帮助。

最快和最优化的方法是 StreamReaderStringBuilder

StringBuilder builder = new StringBuilder();
using (StreamReader reader = new StreamReader(@"c:\email.txt"))
{
    while (!reader.EndOfStream)
    {
        var line = reader.ReadLine();
        if (line.EndsWith(myWord))
        {
            builder.AppendLine(line);
        }
    }
}
outputEmails.Text = builder.ToString();