是File.Replace
做原子/事务操作,如果发生崩溃或电源故障,目标文件永远不会丢失,也不会丢失部分文件(即原始文件或新文件)?
如果没有,是否有另一种方法可以防止这种情况?
注意:这将在Windows 7或更高版本的NTFS驱动器上,我理解支持事务.
注意:我问的是保存在一个原子庄园而不关心一个单独的进程也像这个问题那样打开文件.
File.Replace
在ReplaceFile
内部使用WinAPI函数(当然在Windows上).但是,即使在该函数中,原子性也不是记录在案的行为,并且文档有些含糊不清.
首先,如果您想要一致性,则必须使用备份文件.根据文件:
[移动文件失败时...]如果指定了lpBackupFileName,则替换和替换文件将保留其原始文件名.否则,替换的文件不再存在,替换文件以其原始名称存在.
另一种失败模式导致
[移动文件失败时...]替换文件仍以其原始名称存在; 但是,它继承了它正在替换的文件中的文件流和属性.要替换的文件仍然存在不同的名称.如果指定了lpBackupFileName,则它将是替换文件的名称.
这是最糟糕的文档行为 - 您仍然拥有这两个文件,但要"复制"的文件已经更改了其安全属性.如果您使用具有有限权限的服务来编写文件,则可能会出现问题.
最后,当删除失败时,没有任何反应.
那么,整个操作是原子的吗?即使它没有正式记录,我们也有一些指示.首先,只要您使用备份文件选项,替换操作最终是文件ID的交换(以及所有文件属性的单向更新); 这是一个在NTFS上是事务性的操作,所以我的期望是这部分实际上是原子的,只要你不必担心文件属性,ACL和备用数据流.
但是,这种行为不是契约性的,也不File.Replace
是ReplaceFile
.如果您需要一种实施跨性别操作的合同方式,则需要使用TxF.两个主要问题是,一个,TxF仅支持从Vista开始,两个,它在实践中使用不多,并且被弃用.Bummer :)微软推荐的替代TxF的方式记录在https://msdn.microsoft.com/en-us/library/windows/desktop/hh802690%28v=vs.85%29.aspx中 - 包括使用ReplaceFile
(在.NET中暴露File.Replace
).