簡體   English   中英

如何在C#中高效地編寫大文本文件?

[英]How to efficiently write a large text file in C#?

我正在 C# 中創建一個方法,它為Google Product 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());
  }
}

我想知道 StringBuilder 是否適合這項工作。 如果我改用 TextWriter 會不會有性能提升?

我對 IO 性能一無所知,因此將不勝感激任何幫助或一般改進。 謝謝。

文件 I/O 操作通常在現代操作系統中得到了很好的優化。 您不應該嘗試在內存中為文件組裝整個字符串……只需將其逐個寫出。 FileStream將負責緩沖和其他性能考慮。

您可以通過移動以下內容輕松進行此更改:

using (StreamWriter outfile = new StreamWriter(filePath)) {

到函數的頂部,並擺脫直接寫入文件的StringBuilder

避免在內存中構建大字符串的原因有幾個:

  1. 它實際上可能表現得更糟,因為StringBuilder必須在您寫入時增加其容量,從而導致重新分配和復制內存。
  2. 它可能需要比物理分配更多的內存 - 這可能導致使用比 RAM 慢得多的虛擬內存(交換文件)。
  3. 對於真正的大文件 (> 2Gb),您將耗盡地址空間(在 32 位平台上)並且永遠無法完成。
  4. 要將StringBuilder內容寫入文件,您必須使用ToString()有效地使進程的內存消耗加倍,因為兩個副本都必須在內存中一段時間​​。 如果您的地址空間足夠碎片化,以至於無法分配單個連續的內存塊,則此操作也可能會失敗。

只需移動using語句,使其包含整個代碼,然后直接寫入文件。 我認為首先將其全部保存在內存中沒有意義。

使用 StreamWriter.Write 一次寫入一個字符串,而不是在 StringBuilder 中緩存所有內容。

這可能是舊的,但我有一個大約有 1700 萬行的文件要寫,所以我最終每 10k 行一次批處理寫入,類似於這些行

for (i6 = 1; i6 <= ball; i6++) 
{ //this is middle of 6 deep nest ..
  counter++;
  // modus to get a value at every so often 10k lines
  divtrue = counter % 10000; // remainder operator % for 10k
  //  build the string of fields with \n at the end 
  lineout = lineout + whatever 
  // the magic 10k block here
  if (divtrue.Equals(0))  
  {
     using (StreamWriter outFile = new StreamWriter(@filepath, true))
     { 
         //  write the 10k lines with .write NOT writeline..
         outFile.Write(lineout); 
     } 
     // reset the string so we dont do silly like memory overflow
     lineout = ""; 
  }
}

在我的情況下,它比一次一行快得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM