3

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.OpenFile.Move. 前:

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

后:

File.Move(filePath, filePath);

现在它可以在第二台服务器(Win2003SP1)上运行,而不能在第一台服务器(Win2003SP2)上运行。

有谁知道它为什么会这样工作?

4

4 回答 4

4

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

于 2012-08-28T10:35:42.253 回答
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如果您还catch Exception...

于 2012-08-28T10:13:00.407 回答
0

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

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

//or 

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

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

如果您正在寻找其他东西,请告诉我。

于 2012-08-28T10:05:01.667 回答
0

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

于 2012-08-29T10:26:47.623 回答