C# 在StringBuilder中先存储File.AppendText或File.WriteAllText,哪些会消耗更少的资源,速度更快?

C# 在StringBuilder中先存储File.AppendText或File.WriteAllText,哪些会消耗更少的资源,速度更快?,c#,performance,streamwriter,.net,C#,Performance,Streamwriter,.net,我必须将数千行动态生成的行写入一个文本文件。 我有两个选择,它消耗更少的资源,比另一个更快 A.使用StringBuilder和File.WriteAllText StringBuilder sb = new StringBuilder(); foreach(Data dataItem in Datas) { sb.AppendLine( String.Format( "{0}, {1}-{2}", dataItem.Pr

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

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)); 
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));
    }
}
B.使用File.AppendText

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)); 
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));
    }
}

您至少还有一个选择,使用

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

不过,它可能与您的第二种方法几乎完全相同。我只是给你看第三种选择。这种方法的唯一优点是可以为它提供Linq序列,这有时很有用

I/O速度将使任何其他考虑因素相形见绌,因此您应该像上面提到的那样将内存使用降至最低(当然,还要考虑过早优化的危险!)


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

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

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

通过增加输出缓冲区的大小,可以大大提高速度。而不是

File.AppendText("filename")
使用以下内容创建流:

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

64K的缓冲区大小比默认的4K缓冲区大小提供了更好的性能。您可以做得更大,但我发现大于64K会带来最小的性能提升,在某些系统上实际上会降低性能。

我需要尽快完成此操作,因为这涉及到网络和数据库写入。我有一些相关的瓶颈,所以我问这个问题是因为我需要,而不是因为我不知道你链接的文章。我不确定速度应该是你主要关心的问题。内存使用率显然是你做出决定的动力。如果数据总是很小,那么你可以运行一些测试来确定哪个更快。我想我最喜欢这个。回答得好。我很惊讶,因为行数减少了。更清晰。但什么是var数据?是字符串数组吗?@AlbertoLeón:
数据
是一个
IEnumerable
。您需要通读LINQ以了解其后果。对于那些不喜欢LINQ特殊语法并喜欢函数样式的人,应该是
var data=Datas.Select(item=>string.Format(…)StreamWriter
使用它来防止它必须为每个字符调用Windows
Write
函数。它缓冲数据,然后将其写入块中。如果你试图写一个比缓冲区大的块,你就不会出错。太好了!然后,我认为您的解决方案改进了我的第二个方案,我喜欢它。“我发现大于64K会带来最小的性能提升,在某些系统上实际上会降低性能。”。我很想知道,怎么做?通过显式基准测试还是隐式地从应用程序中的真实数据?@user1451111我没有进行严格的基准测试。我在不同的缓冲区大小下测试了我的几个应用程序。自从我收集了答案所依据的数据后,.NET Framework中发生了很多变化。现在情况可能会大不相同。