【问题标题】:File.Move fails when preceded by a File.DeleteFile.Move 前面有 File.Delete 时失败
【发布时间】:2011-04-18 15:11:05
【问题描述】:

我们有一个 MoveFile 方法,该方法通常可以工作,但在客户站点总是失败。

if (File.Exists(target))
{
    File.Delete(target);
}

File.Move(source, target);

File.Move 的调用反复失败

System.IO.IOException: Cannot create a file when that file already exists.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.__Error.WinIOError()
   at System.IO.File.Move(String sourceFileName, String destFileName)

我们对该方法的调用进行了错误处理,但我们无法弄清楚为什么File.Delete 不起作用并且没有抛出任何东西。

我们虽然是关于文件权限的,但是File.Delete 会抛出一个UnauthorizedAccessException

File.Move 在删除该特定文件之前,是否有任何其他原因会导致“文件已存在”失败?

【问题讨论】:

  • 好奇:如果将 File.Move 包装在类似的 if(File.Exists(..)) 中会发生什么?
  • 删除后移动失败的一个可能原因是文件句柄可能仍在系统的某些进程中打开,例如防病毒扫描程序或搜索索引器。由于 File.Delete 备注部分明确指出“Windows NT 4.0 平台注意:Delete 不会删除为正常 I/O 打开的文件或内存映射的文件。”,而是将其标记为 Delete 并进一步调用访问被拒绝异常。

标签: c# io


【解决方案1】:

你能颠倒逻辑吗​​?

File.Copy (source, target, true) 

然后覆盖目标

File.Delete(source)

【讨论】:

  • 好的,这已经过测试并且可以工作。谢谢,很抱歉延迟接受答案,当您依赖 TeamViewer 访问权限在客户站点部署应用程序时,测试这样的事情并不容易。
  • 我知道这种感觉!我可能应该指出(如果不是很明显的话),如果文件很大,这样做有一个缺点:如果源和目标在同一个磁盘上,文件移动将非常快,而复制数据可能需要一段时间。但在较小的文件上,速度差异将是微不足道的。
【解决方案2】:

过去,我发现系统删除文件的速度往往比程序运行的“慢”。

理想情况下,您需要先检查文件是否已被删除,然后再尝试将文件移动到相应位置。通常你可以用一个简单的 Thread.Sleep(200) 或类似的方法来解决这个问题,但这可能不是最可靠的方法!

【讨论】:

  • 基于此的稍微更可靠的方法是使用 Thread.Sleep 在循环中轮询文件的存在并等待它被删除,直到达到某个最大超时。跨度>
  • 这是一个不可避免的竞争条件。重复重试是唯一的方法。
【解决方案3】:

我相信如果其他人使用 FileShare.Delete 选项打开文件(即允许删除),就会发生这种情况。在这种情况下,文件将被标记为删除,但在关闭另一个句柄之前不会真正被删除。

我不确定哪些进程可以以这种方式打开文件 - 防病毒软件是一种可能性。

【讨论】:

    【解决方案4】:

    我认为你可能会得到更好的结果:

    System.IO.File.Copy(sourceFileName, destFileName, overwrite);
    

    这样overwrite = true

    如果旧文件存在,这将覆盖旧文件,而不用担心单独删除它。

    然后您可以根据需要删除原始文件。

    【讨论】:

      【解决方案5】:

      这是避免复制或轮询删除的更好方法 ---
      假设我们有 File_A 和 File_B。我们想将 File_B 移动到 File_A 上。
      步骤:
      1) 将 File_A 重命名(移动)为第三个名称 File_C。
      2) 删除 File_C。
      3) 将 File_B 重命名(移动)为 File_A。

      File.Move("File_A", "File_C");
      File.Delete("File_C");
      File.Move("File_B", "File_A");
      

      这消除了在将新文件移动到原始文件时被删除的原始文件挂起的竞争条件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-11
        • 1970-01-01
        • 1970-01-01
        • 2018-02-20
        • 1970-01-01
        • 2015-11-06
        相关资源
        最近更新 更多