当File.Move执行时,File.Open不会抛出IOException

时间:2012-08-28 09:56:20

标签: c# ioexception

我在不同服务器上面临IOException的奇怪问题。这是我的故事:

我有win服务器(C#)监视文件夹的文件更改。此外,FTP服务器(WinSSHD)指向同一文件夹。当有人上传文件时,WinService检查是否写入完成。如果上传了文件,WinService会通过File.Move方法重命名它。

是否通过File.Open方法进行写入完成检查。像这样:

public static bool IsWriteComplete(string filePath)
{
    bool isWriteComplete;
    FileStream stream = null;
    try
    {
        stream = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite|FileShare.Delete);
        isWriteComplete = true;
    }
    catch (IOException)
    {
        isWriteComplete = false;
    }
    catch (Exception ex)
    {
        isWriteComplete = false;
    }
    finally
    {
        if (stream != null) { stream.Close(); }
    }
    return isWriteComplete;
}

出于某种原因,在一台服务器上它完美运行(Win2003SP2)而在另一台服务器上运行(Win2003SP1)根本不起作用。 IsWriteComplete方法表示True,WinServer尝试移动文件并在IOException之后消失。我没有找到任何有关此类问题的参考资料。

要解决此问题,请将File.Open替换为File.Move。 之前:

stream = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite|FileShare.Delete);

后:

File.Move(filePath, filePath);

现在它适用于第二台服务器(Win2003SP1),并且不适用于第一台(Win2003SP2)。

有人知道为什么会这样吗?

4 个答案:

答案 0 :(得分:4)

当您使用File.Open时,即使您使用FileShare.None也有“竞争条件” - 关闭文件后,另一个线程/进程可以潜入并锁定文件(打开它),然后再调用File 。移动。这个其他进程可能不是FTP服务器,但可能是您甚至不知道的东西,例如病毒检查程序。因此,您应该使用File.Move而不是File.Open,如果File.Move失败,则捕获IOException,然后重试,直到成功。

答案 1 :(得分:1)

当您使用FileShare.ReadWrite|FileShare.Delete时,允许其他进程在您打开文件时读取,写入或删除该文件。另一方面,您可以打开文件,而其他人也可以访问它。因此,请尝试FileShare.None以独占方式打开文件,只要FTP服务器正在使用该文件,该文件就会失败。

此外,您应该使用FileAccess.ReadWrite来确保您拥有该文件的完全访问权限。您不知道FTP服务器如何锁定文件,也许它允许其他进程以读取模式打开文件,并在上载仍在进行时拒绝写入模式。所以,FileAccess.ReadWrite更好。

MSDN参考:http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspxhttp://msdn.microsoft.com/en-us/library/system.io.fileaccess.aspx

关于您的代码:

catch (IOException)
{
    isWriteComplete = false;
}
catch (Exception ex)
{
    isWriteComplete = false;
}

如果你也抓住了IOException ...... {/ p>,那么Exception的阻止块是不必要的

答案 2 :(得分:0)

或者,你可以用其他方式检查然后打开方法。

FileInfo fileInfo = new FileInfo(filePath);
bool isNormal = ((fileInfo.Attributes & FileAttributes.Normal) == FileAttributes.Normal);

//or 

bool isReadOnly = ((fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly);

您可以通过任何一种方式找到该方法,以了解文件是否可用。您可以根据状态继续。

如果您正在寻找其他一些事情,请告诉我。

答案 3 :(得分:0)

找到行为的根本原因。 安装了不同的FTP服务:Techia。出于某种原因,Tectia没有对上传文件设置写锁定。这就是File.Open(filePath,FileAccess.Write)不会抛出IOException的原因。