模拟文件.如果目标已存在,则移动

本文关键字:移动 存在 文件 如果 目标 模拟 | 更新日期: 2023-09-27 18:32:04

来自File.Move的文档:

请注意,如果尝试通过将同名文件移动到该目录中来替换文件,则会获得 IOException。不能使用 Move 方法覆盖现有文件。

简而言之,你不能在Move上覆盖,所以为了便于在 Move 上覆盖,我通过执行一个File.Copy然后File.Delete来模仿该行为。像这样:

if (File.Exists(dstFileName))
{
    // System.IO.File.Move cannot be used to overwrite existing files, so we're going
    // to simulate that behavior with a Copy & Delete.
    File.Copy(procContext.FileName, dstFileName);
    File.Delete(procContext.FileName);
}
else
    File.Move(procContext.FileName, dstFileName);

我的问题是:是否有任何我需要防范的情况,这些情况可能导致源文件被删除而没有首先成功复制?

我从阅读文档中获得的理解是,由于File.Copy不返回任何内容,因此在任何情况下它都不会成功,因此它应该抛出异常。有没有人遇到过任何不是这种情况的情况?

模拟文件.如果目标已存在,则移动

我建议您先探测目标文件是否存在,如果是,请将其删除。然后执行正常的移动操作。

由于此序列不是原子序列,因此如果目标存在,您可能希望重命名它而不是删除它,以避免在移动失败时丢失它。

正确的方法是调用

File.Replace(source, destination, copy)

这对我来说是

诀窍

如果操作系统不能为您提供良好的原子操作,则很难模拟原子操作。 Move在某些文件系统上是原子的,但不是在所有文件系统上是原子的,但在将磁盘移动到磁盘时则不是。

在同一个磁盘的情况下,Delete + Move 有点优雅(快速和安全),因为它不会以任何方式真正填充数据。 您可以进一步将其扩展到

try
{
    Move(dest, tmp);
    Move(src, dest);
    Delete(tmp);
}
catch
{
    try
    {
        Move(tmp, dest);
    }
    catch
    {
    }
    throw;
}

(这样,当您没有完成移动所需的权限时,丢失目标文件的可能性就会降低。

在您不知道它是同一个磁盘的情况下,您的解决方案足够安全且足够简单。 但是,它甚至会在同一磁盘内复制数据,从而为您带来更大的电源故障风险窗口。

这是安全的。File.Copy 要么完全成功,要么抛出。当然,删除可能会失败,将源文件作为垃圾留下。

但是,如果您的计算机崩溃,则无法保证复制已强化数据。在这种情况下,您可能会丢失数据。

在正常操作期间,这是安全的。

检查文件"目标"是否存在。如果没有,请复制您的文件。

如果是:将"目标"移动到临时目录,在那里您可以确定移动将成功。您可以在 Temp 中生成名为 auf an UUID 的子目录。然后复制您的文件。