使用File.Copy()的IOException,尽管先前的File.Exists()检查

时间:2011-03-07 13:42:42

标签: c# .net

这与简单的文件复制操作代码有关。我的要求是只有新文件从源文件夹复制到目标文件夹,所以在复制文件之前,我检查一下:

  • 它存在于源文件夹
  • 目标文件夹中不存在

在此之后,我继续进行复制操作 但是,我随机获得一个IOException,声明“文件< filename>已经存在。”
现在,我在2台服务器上运行此代码(作为win服务的一部分),所以我愿意承认,也许,只是可能,在Server1检查条件并继续复制文件的短暂间隔内,Server2复制它到目标,导致Server1上的IOException 但是,我有几千个文件被复制,我得到了数千个这个错误。这怎么可能?我错过了什么?这是代码:

try
{
    if(File.Exists(String.Format("{0}\\{1}",pstrSourcePath,strFileName)) && !File.Exists(String.Format("{0}\\{1}",pstrDestPath,strFileName)))
            File.Copy(String.Format("{0}\\{1}",pstrSourcePath,strFileName),String.Format("{0}\\{1}",pstrDestPath,strFileName))     
}
catch(IOException ioEx)
{
    txtDesc.Value=ioEx.Message;
}

3 个答案:

答案 0 :(得分:6)

想象这是一个权限问题。来自File.Exists的文档:

  

如果调用者没有足够的权限来读取指定的文件,则不会抛出任何异常,并且无论路径是否存在,该方法都会返回false。

文件可能存在,但您的代码无权检查它?

请注意,如果您为每个文件使用string.Format 一次并将结果保存到临时变量,则代码会更清晰。最好使用Path.Combine代替string.Format,如下所示:

string sourcePath = Path.Combine(pstrSourcePath, strFileName);
string targetPath = Path.Combine(pstrDestPath, strFileName);
if (File.Exists(sourcePath) && !File.Exists(targetPath))
{
    File.Copy(sourcePath, targetPath);
}

(我也放弃了strpstr前缀,但是嘿......)

答案 1 :(得分:1)

两个服务器场景足以解释问题。请注意,他们将具有自动同步彼此的复制操作的诀窍。无论服务器背后的是什么,都会很快赶上,因为该文件已存在于目标机器的文件系统缓存中。

你必须放弃File.Exist测试,它无法在多任务操作系统上可靠地工作。竞争条件无法解决,因为Windows和.NET都没有例如IsFileLocked()方法。只需调用File.Copy()即可。如果文件已存在,您当然会得到IOException。使用Marshal.GetLastWin32Error()过滤掉异常消息。 ERROR_FILE_EXISTS错误代码为80。

答案 2 :(得分:0)

同样的事情发生在我身上,我无法弄明白。在我的情况下,我总是写到一个新的位置,但有时我收到相同的错误。当我查看该位置时,有一个文件,其名称大小为零字节。我可以保证该文件之前不存在,而其他一些进程也不会写入该位置。这是复制到网络共享,不知道这是否重要,但我想我会提到它。它几乎就像File.Copy操作正在写文件,然后犯错,因为文件存在(但并非总是如此)。我正在记录我的复制操作,因为我递归目录结构并且看不到可能重叠的重复复制操作。