2016-01-08 2 views
10

Делает ли File.Replace операцию атома/транзакции, так что при сбое или сбое питания целевой файл никогда не будет отсутствовать, а также неполный файл (то есть будет оригиналом или новым файлом)?C# File.Replace защита от сбоя

Если нет, существует ли другой способ защиты от этого сценария?

Примечание: Это будет на диске NTFS с Windows 7 или более поздней версией, что, как я понимаю, поддерживает транзакции.

Примечание: Я прошу о сохранении в атомной усадьбе и не беспокоюсь о отдельном процессе, также имеющем открытый файл, как this question.

+0

Я полагаю, что ответ на этот вопрос в значительной степени зависит от того, находятся ли файлы на двух отдельных физических носителях. – Rob

+0

Это не дубликат. Связанный вопрос * не * охватывает, является ли операция *** атомарной ***, скорее, она исправляет проблему при попытке удалить файл. – Rob

+0

это не имеет никакого смысла в реализации, а скорее на уровне ОС. –

ответ

3

File.Replace использует функцию WinAPI ReplaceFile внутренне (в Windows, конечно). Однако атомарность не является документированным поведением даже в этой функции, и документация несколько неоднозначна.

Во-первых, если вы хотите согласованности, вы должны указать файл. Согласно документации:

[При перемещении файла сбой ...] Если указано lpBackupFileName, замененные и заменяющие файлы сохраняют свои исходные имена файлов. В противном случае замененный файл больше не существует, и файл замены существует под его первоначальным именем.

Другие результаты в режиме отказа в

[При перемещении файла не удается ...] Файл замены до сих пор существует под своим первоначальным именем; однако он унаследовал файловые потоки и атрибуты из файла, который он заменяет. Файл, который нужно заменить, все еще существует с другим именем. Если указано lpBackupFileName, это будет имя замененного файла.

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

И наконец, когда удаление не удалось, ничего не происходит.

Итак, вся операция атома? Хотя это официально не документировано, у нас есть несколько указателей. Во-первых, операция замены - это, в конечном счете, своп идентификаторов файлов (и одностороннее обновление всех атрибутов файла), если вы используете опцию резервного файла; это транзакция транзакции на NTFS, поэтому я ожидал, что эта часть будет эффективно атомной, если вам не нужно беспокоиться об атрибутах файлов, ACL и альтернативных потоках данных.

Однако это поведение не является договором, ни для File.Replace, ни для ReplaceFile. Если вам нужен контрактный способ реализации трансакционных операций, вам необходимо использовать TxF. Две основные проблемы: один, TxF поддерживается только с Vista, и два, он практически не использовался на практике и устарел.Bummer :) Официальный Microsoft-рекомендованный способ замены TxF документирован в https://msdn.microsoft.com/en-us/library/windows/desktop/hh802690%28v=vs.85%29.aspx - и включает в себя использование ReplaceFile (отображается в .NET как File.Replace).