Как эффективно записать файл крупного текста в C#?

Я создаю метод в C#, который генерирует текстовый файл для Канала продукта Google. Канал будет содержать вверх 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 так никакая справка, или общие улучшения ценились бы.Спасибо.

36
задан jessegavin 4 August 2010 в 15:39
поделиться

3 ответа

Операции файлового ввода-вывода обычно хорошо оптимизированы в современных операционных системах. Не пытайтесь собрать всю строку для файла в памяти ... просто запишите ее по частям. FileStream позаботится о буферизации и других аспектах производительности.

Вы можете легко внести это изменение, переместив:

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

в начало функции и избавившись от записи StringBuilder непосредственно в файл.

Есть несколько причин, по которым вам следует избегать создания больших строк в памяти:

  1. На самом деле он может работать хуже, потому что StringBuilder должен увеличивать свою емкость по мере того, как вы пишете в него, что приводит к перераспределению и копирование памяти.
  2. Может потребоваться больше памяти, чем вы можете выделить физически, что может привести к использованию виртуальной памяти (файла подкачки), которая работает намного медленнее, чем ОЗУ.
  3. Для действительно больших файлов (> 2 ГБ) у вас закончится адресное пространство (на 32-битных платформах), и вы никогда не сможете завершить операцию.
  4. Чтобы записать содержимое StringBuilder в файл, вы должны использовать ToString () , что эффективно удваивает потребление памяти процессом, поскольку обе копии должны находиться в памяти в течение периода время. Эта операция также может завершиться неудачно, если ваше адресное пространство достаточно фрагментировано, так что нельзя выделить один непрерывный блок памяти.
69
ответ дан 27 November 2019 в 05:19
поделиться

Просто переместите с помощью оператора , чтобы он охватил весь ваш код, и напишите прямо в файл. Не вижу смысла сначала держать все это в памяти.

26
ответ дан 27 November 2019 в 05:19
поделиться

Записывать по одной строке, используя StreamWriter.Write, а не кэшировать все в StringBuilder.

12
ответ дан 27 November 2019 в 05:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: