StreamReader 对于大文件非常慢

StreamReader very slow for big files

我想读入一个文件,在本例中是 3mb 这样做大约需要 50-60 秒,这看起来很慢。有谁知道如何让它更快?

string text = null;
using (StreamReader sr = new StreamReader(file, Encoding.Default))
{
    string line;
    while ((line = sr.ReadLine()) != null)
    {
        text += (line);
        backgroundWorker1.ReportProgress(text.Length);
    }
}

我还需要使用后台工作程序,以便报告已加载的百分比(对于大约 500mb 到 1gb 的文件)

使用 StringBuilder 创建您的行 - 它比字符串连接更高效。

using System.Text;

//...

StringBuilder text = new StringBuilder();
using (StreamReader sr = new StreamReader(file, Encoding.Default))
{
    string line;
    while ((line = sr.ReadLine()) != null)
    {
        text.Append(line);
        backgroundWorker1.ReportProgress(text.Length);
    }
}

// ...
// Do something with the file you have read in.
Console.WriteLine(text.ToString());

您可以使用这一行:

string text = System.IO.File.ReadAllText(file);

StreamReader very slow for big files C#

不,不是。如果您完成了 运行 概要分析器的基本功课,您会发现您花费的时间并未花在流中 reader。

text += (line);

此行正在创建一个新字符串。为此必须分配新内存。对于大文件,这是创建的大量垃圾。而且时间越长,复制操作越多。

如果这就是您使用它的目的

backgroundWorker1.ReportProgress(text.Length);

也没用。你也可以有一个

int textLength = 0

然后你设置

textLength += line.Length

没有所有的文本操作。

你应该知道的。性能问题?永远不要假设,我们总是一个分析器——它会很快向您展示问题。这是基本调试。

一些背景数学,顺便说一句:

(for files around 500mb to 1gb)

这意味着一旦你加载了 500mb 的数据,你的代码就会进行 500mb(如果文件是 unicode)到 1gb(字符串是 ascii 文件大小的两倍)每行复制操作。

您可能需要查看计算机的内存速度。根据服务器等因素,您可能会被限制为每秒 50gb(高端 X99 - 较新的 DDR 4 内存速度更快,但工作站通常具有更少的通道,因此再次变慢)并且副本计数加倍(读取和写入)。这意味着您真正开始 运行 进入 "copying the string is overloading them memory bus" 场景。