Stream.Write是多次更好还是连接字符串和Stream.Write一次?

时间:2014-12-26 19:07:58

标签: c# .net file stream

我只是想知道,在性能方面,哪个更好(我在FileStream中使用StreamWriter):

  1. 多次调用Stream.Write():
  2. StreamWriter sw = new StreamWriter(fs);
    for (int i = 0; i < 100; i++)
    {
        sw.Write(myList[i].ToString());
    }
    

    1. 将我的所有字符串连接成一个字符串,然后调用Steam.Write()一次:
    2. StreamWriter sw = new StreamWriter(fs);
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < 100; i++)
      {
          sb.Append(myList[i].ToString());
      }
      sw.Write(sb.ToString());
      

      谢谢!

3 个答案:

答案 0 :(得分:2)

对此没有单一答案。您可以想象逐字节或逐字符写入通常会导致开销,因为每个数据块都会经过抽象层。

然而,您也可以想象尽可能缓冲可能不是最佳的,即。如果您通过网络流发送数据,您希望网络尽快开始传输数据。而且你的应用程序正在忙着缓冲,所以也许你只是移动延迟而不是修复任何东西。

如果FileStream操作系统负责缓冲,在正常情况下您可能不会注意到两种方法之间的任何差异。

只需编写最适合您应用程序的数据,如果您发现这是应用程序的瓶颈,请在StreamWriter和基础Stream之间实现缓冲流层以对抗问题

答案 1 :(得分:2)

根据我的个人经验,在选择一个或另一个之前还应考虑其他事项:如果您逐行写入流,则完整文本的每一行都有可能出现I / O异常(特别是在写入磁盘);因此,您要编写的行越多,您的代码就越容易出错。因此,如果您的两种方法之间没有显着差异,请考虑第二种方法,或者如果在编写完整文本的一半时出现异常,请准备好恢复代码。

答案 2 :(得分:0)

我使用3种不同的方法来测量持续时间:

class Program
{
    private static readonly int NumLines = 100000;
    private static readonly int NumWords = 200;
    private static readonly string Word = "Oberbuergermeister";

    static void Main(string[] args)
    {
        var stopWatch = new Stopwatch();

        // approach 1: use string builder to cache all, then write
        stopWatch.Start();
        Approach1();
        stopWatch.Stop();
        Console.WriteLine(stopWatch.Elapsed.ToString());
        stopWatch.Reset();

        // approach 2: write stuff line by line
        stopWatch.Start();
        Approach2();
        stopWatch.Stop();
        Console.WriteLine(stopWatch.Elapsed.ToString());
        stopWatch.Reset();

        // approach 3: write stuff string by string
        stopWatch.Start();
        Approach3();
        stopWatch.Stop();
        Console.WriteLine(stopWatch.Elapsed.ToString());
    }

    private static void Approach1()
    {
        var writer = new System.IO.StreamWriter("C:\\temp\\1");

        var builder = new StringBuilder();
        for (int cnt1 = 0; cnt1 < NumLines; cnt1++)
        {
            for (int cnt2 = 0; cnt2 < NumWords; cnt2++)
            {
                builder.Append(Word);
                builder.Append(";");
            }
            builder.AppendLine();
        }

        writer.WriteLine(builder.ToString());

        writer.Close();
    }

    private static void Approach2()
    {
        var writer = new System.IO.StreamWriter("C:\\temp\\2");

        var builder = new StringBuilder();
        for (int cnt1 = 0; cnt1 < NumLines; cnt1++)
        {
            for (int cnt2 = 0; cnt2 < NumWords; cnt2++)
            {
                builder.Append(Word);
                builder.Append(";");
            }
            writer.WriteLine(builder.ToString());
            builder.Clear();
        }

        writer.Close();
    }

    private static void Approach3()
    {
        var writer = new System.IO.StreamWriter("C:\\temp\\3");

        for (int cnt1 = 0; cnt1 < NumLines; cnt1++)
        {
            for (int cnt2 = 0; cnt2 < NumWords; cnt2++)
            {
                writer.Write(Word);
                writer.Write(";");
            }
            writer.WriteLine();
        }

        writer.Close();
    }
}

以下是输出:

00:00:02.8457431
00:00:01.5492287
00:00:01.4843888

看起来最好是尽可能多地调用StreamWriter.Write(),并将缓存完全留给.NET。我还没有尝试过逐个字符,但逐行似乎仍然足够好。