2011-04-18 21 views
11

失败我们有一个MoveFile方法,通常可以工作,但在客户站点保持失败。File.Move前面有一个File.Delete

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在“文件已存在”失败时导致该特定文件被删除?

+0

好奇:如果将File.Move包装在类似的if(File.Exists(..))中会发生什么? – razlebe 2011-04-18 15:16:24

+1

删除后移动失败的一个可能原因是文件句柄可能仍在系统中的某个进程中打开,例如反病毒扫描程序或搜索索引器。由于File.Delete注释部分明确指出“Windows NT 4.0平台注意:删除不会删除为正常I/O或存储器映射的文件打开的文件”,而只是将其标记为“删除”,并进一步调用give拒绝访问异常。 – kiran 2014-02-11 09:55:25

回答

11

你能逆转逻辑吗?

File.Copy (source, target, true) 

覆盖目标则

File.Delete(source) 
+0

不错的想法:) +1 – 2011-04-19 13:24:53

+0

好的,这是测试和工作。谢谢,对于延迟接受答案感到抱歉,当您依赖TeamViewer访问来在客户站点部署应用程序时,不容易测试这样的事情。 – 2011-04-20 15:06:51

+0

我知道这种感觉!如果文件很大,我应该指出(如果不是非常明显),如果源文件和目标文件位于同一磁盘上,则文件移动非常快,而复制数据可能需要一段时间。但是对于较小的文件,速度差异将是微不足道的。 – MarcE 2011-04-20 16:14:35

4

在过去,我发现系统倾向于删除比您的程序运行“慢”的文件。

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

+1

基于此的一个稍微可靠的方法是在一个带有Thread.Sleep的循环中轮询文件的存在并等待它被删除,直到达到某个最大超时。 – devios1 2011-04-18 15:16:00

+0

这是一个不可避免的竞争条件。重复重试是唯一的方法。 – Tergiver 2011-04-18 15:16:44

+2

也许使用FileSystemWatcher而不是Thread.Sleep? – razlebe 2011-04-18 15:24:00

4

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

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

3

我想你可能会得到更好的结果出来:

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

使overwrite = true

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

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

0

这里有一个更好的方法,避免复制或轮询删除---
假设我们有FILE_A和FILE_B。我们想通过File_A移动File_B。
步骤:
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"); 

这消除了在原始文件被删除左右,而新文件被移动到原始文件挂起的竞争条件。