如何在C#中有效地编写大文本文件?

jes*_*vin 36 c# io text-files

我正在使用C#创建一个方法,为Google Product Feed生成一个文本文件.Feed将包含超过30,000条记录,文本文件目前的重量约为7Mb.

这是我目前正在使用的代码(为简洁起见,删除了一些代码).

public static void GenerateTextFile(string filePath) {

  var sb = new StringBuilder(1000);
  sb.Append("availability").Append("\t");
  sb.Append("condition").Append("\t");
  sb.Append("description").Append("\t");
  // repetitive code hidden for brevity ...
  sb.Append(Environment.NewLine);

  var items = inventoryRepo.GetItemsForSale();

  foreach (var p in items) {
    sb.Append("in stock").Append("\t");
    sb.Append("used").Append("\t");
    sb.Append(p.Description).Append("\t");
    // repetitive code hidden for brevity ...
    sb.AppendLine();
  }

  using (StreamWriter outfile = new StreamWriter(filePath)) {
      result.Append("Writing text file to disk.").AppendLine();
      outfile.Write(sb.ToString());
  }
}
Run Code Online (Sandbox Code Playgroud)

我想知道StringBuilder是否适合这项工作.如果我使用TextWriter,会有性能提升吗?

我不太了解IO性能,所以任何帮助或一般改进都将不胜感激.谢谢.

LBu*_*kin 69

文件I/O操作通常在现代操作系统中得到很好的优化.你不应该尝试在内存中组装文件的整个字符串......只需逐个写出来.这FileStream将考虑缓冲和其他性能考虑因素.

您可以通过移动轻松地进行此更改:

using (StreamWriter outfile = new StreamWriter(filePath)) {
Run Code Online (Sandbox Code Playgroud)

到函数的顶部,并StringBuilder取而代之的是直接写入文件.

有几个原因可以避免在内存中构建大字符串:

  1. 它实际上可能会表现更差,因为在StringBuilder写入时必须增加其容量,从而导致重新分配和复制内存.
  2. 它可能需要比物理分配更多的内存 - 这可能导致使用比RAM慢得多的虚拟内存(交换文件).
  3. 对于真正大的文件(> 2Gb),您将耗尽地址空间(在32位平台上)并且将无法完成.
  4. 要将StringBuilder内容写入您必须使用的文件,ToString()这有效地使进程的内存消耗加倍,因为两个副本必须在内存中保留一段时间.如果地址空间足够碎片,则此操作也可能失败,从而无法分配单个连续的内存块.


Jon*_*eet 26

只需移动using语句,使其包含整个代码,然后直接写入文件.我认为没有必要先将它全部记在内存中.


Ale*_*rey 12

使用StreamWriter.Write一次写一个字符串,而不是在StringBuilder中缓存所有内容.

  • 我真的希望你不要吝啬他一次写一个*位*. (4认同)
  • @MaximusPeters你可能在此期间找到了自己的方式,但也许你使用的是`WriteLine()`方法而不是`Write()`? (2认同)