Лучшая практика для записи больших файлов - PullRequest
0 голосов
/ 07 декабря 2018

Мне нужно написать большой файл в моем проекте.


Что я узнал:

  • Я НЕ должен писатьбольшой файл непосредственно по пути назначения, потому что это может оставить неполный файл в случае сбоя приложения во время его записи.

  • Вместо этого я должен записать во временный файл и переместить (переименовать)Это.(называется атомарной файловой операцией)


Мой фрагмент кода:

[NotNull]
public static async Task WriteAllTextAsync([NotNull] string path, [NotNull] string content) 
{
    string temporaryFilePath = null;
    try {
        temporaryFilePath = Path.GetTempFileName();
        using (var stream = new StreamWriter(temporaryFilePath, true)) {
            await stream.WriteAsync(content).ConfigureAwait(false);
        }            

        File.Delete(path);
        File.Move(temporaryFilePath, path);
    }
    finally {
        if (temporaryFilePath != null) File.Delete(temporaryFilePath);
    }
}

Мой вопрос:

  • Файл будет отсутствовать в случае сбоя приложения между File.Delete и File.Move.Могу ли я избежать этого?

  • Есть ли другие рекомендации по написанию больших файлов?

  • Есть ли какие-либо предложения по моему коду?

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Вы можете использовать File.Replace вместо удаления и перемещения файлов.В случае серьезного сбоя (отключение электричества или что-то в этом роде) вы всегда будете терять данные, вы должны учитывать это.

0 голосов
/ 07 декабря 2018

Файл будет отсутствовать в случае сбоя приложения между File.Delete и File.Move.Могу ли я этого избежать?

Не то, что я знаю, но вы можете обнаружить это - и если вы используете более предсказуемое имя файла, вы можете восстановить его.Это помогает, если вы немного подправите процесс, чтобы использовать три имени файла: цель, «новый» файл и «старый» файл.Процесс становится следующим:

  • Запись в «новый» файл (например, foo.txt.new)
  • Переименование целевого файла в «старый» файл (например, foo.txt.old)
  • Переименуйте «новый» файл в целевой файл
  • Удалите «старый» файл

У вас есть три файла, каждый из которых может присутствовать или отсутствовать.Это может помочь вам обнаружить ситуацию, когда вы читаете новый файл:

  • Нет файлов: пока ничего не записано
  • Просто цель: Все хорошо
  • Назначение и новый: сбой приложения при записи нового файла
  • Назначение и старый: приложению не удалось удалить старый файл
  • Новое и старое: сбой приложения после первого переименования, но перед вторым
  • Все три, или просто старые, или просто новые: происходит нечто очень странное!Возможно, пользователь вмешался

Примечание. Раньше я не знал о File.Replace, но подозреваю, что эффективно - просто более простой и, возможно, более эффективный способ выполнения кода, который выуже делаю.(Это здорово - используйте его!) Хотя процесс восстановления будет таким же.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...