C#文件.替换对崩溃的保护

本文关键字:保护 崩溃 文件 替换 | 更新日期: 2023-09-27 18:29:23

File.Replace是否执行原子/事务操作,以便在发生崩溃或电源故障时,目标文件永远不会丢失,也不会是部分文件(即原始文件或新文件)?

如果没有,是否有其他方法可以防止这种情况发生?

注意:这将在装有Windows7或更高版本的NTFS驱动器上,我知道它支持事务。

注意:我问的是在原子庄园中保存,而不是像这个问题一样打开文件的单独过程。

C#文件.替换对崩溃的保护

File.Replace在内部使用WinAPI函数ReplaceFile(当然是在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)。

File.Replace不是原子的:https://social.msdn.microsoft.com/Forums/vstudio/en-US/848ce6b7-ce52-43ca-b79b-168835837c63/is-filereplace-atomic-on-an-ntfs-filesystem?forum=netfxbcl

"File.Reface()在内部使用对本机Windows API函数ReplaceFile()的调用"https://msdn.microsoft.com/en-us/library/windows/desktop/aa365512(v=vs.85).aspx