我正在监视新文件的文件夹,需要处理它们。问题是偶尔文件打开失败,因为系统还没有完成复制。
测试文件是否完成复制的正确方法是什么?
澄清: 我没有文件夹/文件的写权限,无法控制复制过程(这是用户)。
答案 0 :(得分:11)
我认为唯一可靠的方法是尝试独占打开文件并捕获特定的异常。我通常讨厌使用普通应用程序逻辑的异常,但我担心这种情况没有其他方法(至少我还没有找到):
public bool FileIsDone(string path)
{
try
{
using (File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None))
{
}
}
catch(UnauthorizedAccessException)
{
return false;
}
return true;
}
答案 1 :(得分:2)
不确定“正确的方法”,但您可以使用监控工具(我猜是FileSystemWatcher
)来填充您用于延迟处理的内部队列。或者更好的是:只需使用队列将文件置于打开失败的文件中,以便稍后重试。
答案 2 :(得分:1)
如果您使用的是FileSystemWatcher,我认为这个问题没有一个强大的解决方案。一种方法是稍后尝试/捕获/重试。
答案 3 :(得分:0)
我总是采用的一种方法是在我的副本/传输的末尾创建一个名为“token.txt”而没有内容的文件。我们的想法是,这个文件将在传输操作结束时创建,因此您可以监视此文件的创建,并在创建此文件时开始使用您的文件。当您开始处理文件时,请不要忘记始终删除此令牌文件。
答案 4 :(得分:0)
您还应该涵盖以下情况:文件正被其他程序使用,文件被删除(复制未成功)等。
使用扩展异常处理来涵盖可能发生的所有重要案例。
答案 5 :(得分:0)
这取决于,如果您无法控制复制过程,则重试循环可能是您可以做的最好的。
如果你有控制权:
答案 6 :(得分:0)
事实上,为避免竞争条件,唯一安全的解决方案是重试。
如果您执行以下操作:
while (file is locked)
no-op()
process file()
你冒着另一个进程在while guard和process file语句之间跳跃的风险。无论您如何实施“等待文件可用性”,除非您确保解锁后是第一个访问它的过程,否则您可能不成为第一个用户。
乍一看似乎更有可能,特别是如果有多个人正在观看文件,特别是如果他们正在使用类似文件系统观察者的东西。当然,即便如此,它仍然不太可能......
答案 7 :(得分:0)
文件大吗?
也许您可以尝试计算文件中的md5校验和?
如果您将md5哈希放在文件名中,则可以检索它并尝试重新计算文件的校验和。当md5匹配时,您可以认为该文件已完成。
byte[] md5Hash = null;
MD5 md5 = new MD5CryptoServiceProvider();
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
md5Hash = md5.ComputeHash(fs);
StringBuilder hex = new StringBuilder();
foreach (byte b in md5Hash)
hex.Append(b.ToString("x2"));
答案 8 :(得分:0)
这是我使用的vb.net循环。 每次检查之间等待2秒钟。
Dim donotcopy As Boolean = True
While donotcopy = True
Dim myFile As New FileInfo("Filetocopy")
Dim sizeInBytes As Long = myFile.Length
Thread.Sleep(2000)
Dim myFile2 As New FileInfo("Filetocopy")
Dim sizeInBytes2 As Long = myFile2.Length
If sizeInBytes2 = sizeInBytes Then donotcopy = False
End While