10

我必须将数千个动态生成的行写入文本文件。我有两个选择,哪个消耗更少的资源并且比另一个更快?

A. 使用 StringBuilder 和 File.WriteAllText

StringBuilder sb = new StringBuilder();

foreach(Data dataItem in Datas)
{
    sb.AppendLine(
        String.Format(
            "{0}, {1}-{2}",
            dataItem.Property1,
            dataItem.Property2,
            dataItem.Property3));
}

File.WriteAllText("C:\\example.txt", sb.ToString(), new UTF8Encoding(false)); 

B. 使用 File.AppendText

using(StreamWriter sw = File.AppendText("C:\\example.txt"))
{
    foreach (Data dataItem in Datas)
    {
        sw.WriteLine(
            String.Format(
                "{0}, {1}-{2}",
                dataItem.Property1,
                dataItem.Property2,
                dataItem.Property3));
    }
}
4

2 回答 2

18

您的第一个版本将所有内容放入 aStringBuilder然后写入,将消耗最多的内存。如果文本非常大,则可能会耗尽内存。它有可能更快,但也可能更慢。

第二个选项将使用更少的内存(基本上,只是StreamWriter缓冲区),并且性能非常好。我会推荐这个选项。它执行得很好——可能比第一种方法更好——并且没有同样的内存耗尽的可能性。

您可以通过增加输出缓冲区的大小来加快速度。而不是

File.AppendText("filename")

使用以下命令创建流:

const int BufferSize = 65536;  // 64 Kilobytes
StreamWriter sw = new StreamWriter("filename", true, Encoding.UTF8, BufferSize);

64K 的缓冲区大小比默认的 4K 缓冲区大小提供更好的性能。你可以更大,但我发现大于 64K 的性能提升很小,而且在某些系统上实际上会降低性能。

于 2013-04-24T14:28:33.717 回答
7

您确实至少有一个其他选择,使用File.AppendAllLines()

var data = from item in Datas
            select string.Format("{0}, {1}-{2}", item.Property1, item.Property2, item.Property3);

File.AppendAllLines("Filename", data, new UTF8Encoding(false));

从理论上讲,这将比您的第一种方法使用更少的内存,因为一次只有一行将被缓冲在内存中。

不过,它可能与您的第二种方法几乎完全相同。我只是向你展示第三种选择。这个唯一的好处是你可以给它一个 Linq 序列,这有时很有用。

I/O 速度将使任何其他考虑相形见绌,因此您应该专注于最小化内存使用,正如上面提到的 juharr (当然还要考虑过早优化的危险!)

这意味着使用您的第二种方法,或者我放在这里的方法。

于 2013-04-24T12:25:18.640 回答