How to test if a file is fully copied in .NET

后端 未结 9 1265
小鲜肉
小鲜肉 2021-01-17 12:27

I am monitoring a folder for new files and need to process them. The problem is that occasionally file opening fails, because system has not finished copying it.

Wha

相关标签:
9条回答
  • 2021-01-17 12:27

    I think the only sure way to do this is by trying to open the file exclusively and catching a specific exception. I usually hate using exceptions for normal application logic, but I'm afraid for this scenario there's no other way (at least I haven't found one yet):

    public bool FileIsDone(string path)
    {
      try
      {
        using (File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None))
        {
        }
      }
      catch(UnauthorizedAccessException)
      {
        return false;
      }
    
      return true;
    }
    
    0 讨论(0)
  • 2021-01-17 12:28

    Are the files big?

    Maybe you could try to calculate a the md5 checksum on the file?

    If you put the md5 hash in the filename you could retrieve it and try to recalculate the checksum on the file. When the md5 is a match you could assume that the file is finished.

    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"));
    
    0 讨论(0)
  • 2021-01-17 12:31

    You should also cover cases like: file is in use by other program, file was deleted (copy didn't succeed) etc..

    Use an extended exception handling to cover all important cases that might occur.

    0 讨论(0)
  • 2021-01-17 12:35

    In fact, to avoid race conditions, the only safe solution is to retry.

    If you do something like:

    while (file is locked)
        no-op()
    process file()
    

    You risk another process jumping in between the while guard and the process file statement. No matter how your "wait for file availability" is implemented, unless you can ensure that post-unlock you're the first process to access it, you might not be that first user.

    This is more likely that might seem at first glance, in particular if multiple people are watching the file, and in particular if they're using something like the file-system watcher. Course, it's still not particularly likely even then...

    0 讨论(0)
  • 2021-01-17 12:37

    If you are using FileSystemWatcher I don't think there's a robust solution to this problem. One approach would be try/catch/retry later.

    0 讨论(0)
  • 2021-01-17 12:41

    Here's a vb.net loop I use. It waits 2 seconds between each check.

     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
    
    0 讨论(0)
提交回复
热议问题