我在不同服务器上面临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)。
有人知道为什么会这样吗?
答案 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.aspx和http://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的原因。