Подтвердить что ты не робот

Как проверить, полностью ли скопирован файл в .NET.

Я отслеживаю папку для новых файлов и должен их обрабатывать. Проблема в том, что иногда открытие файла не выполняется, потому что система не закончила его копирование.

Каков правильный способ проверить, завершено ли копирование файла?

Разъяснение: У меня нет прав на запись в папку/файлы и невозможно управлять процессом копирования (это пользователь).

4b9b3361

Ответ 1

Я думаю, что единственный верный способ сделать это - попытаться открыть файл исключительно и поймать конкретное исключение. Я обычно ненавижу использовать исключения для обычной логики приложения, но я боюсь, что для этого сценария нет другого пути (по крайней мере, я еще не нашел его):

public bool FileIsDone(string path)
{
  try
  {
    using (File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None))
    {
    }
  }
  catch(UnauthorizedAccessException)
  {
    return false;
  }

  return true;
}

Ответ 2

Не уверен относительно "правильного пути", но вы можете использовать инструмент мониторинга (FileSystemWatcher, я думаю), чтобы заполнить внутреннюю очередь, которую вы используете для отложенной обработки. Или еще лучше: просто используйте очередь для размещения файлов, в которых был открытый сбой, поэтому вы можете повторить их позже.

Ответ 3

Если вы используете FileSystemWatcher, я не думаю, что там есть надежное решение этой проблемы. Один из подходов - попытка/уловка/повторная попытка позже.

Ответ 4

один подход, который я всегда делаю, - это создать файл в конце моей копии/передачи с именем "token.txt" без содержимого. Идея состоит в том, что этот файл будет создан только в конце операции передачи, поэтому вы можете отслеживать создание этого файла, и когда этот файл будет создан, вы начнете работать с вашими файлами. Не забывайте стирать этот файл токена всегда, когда вы начинаете обрабатывать ваши файлы.

Ответ 5

Вы также должны учитывать такие случаи, как: файл используется другой программой, файл был удален (копия не удалась) и т.д.

Используйте расширенную обработку исключений, чтобы охватить все важные случаи, которые могут возникнуть.

Ответ 6

Это зависит от того, что цикл повтора, вероятно, лучше всего подходит, если у вас нет контроля над процессом копирования.

Если у вас есть контроль:

  • Если папка локальная, вы можете потребовать, чтобы люди, записывающие в нее файлы, блокировали файл для эксклюзивного доступа и освобождали блокировку только после их завершения (что, по-моему, по умолчанию для File.Copy). На стороне .Net у вас может быть простой цикл повтора с периодом охлаждения.
    • В качестве альтернативы вы можете записать файл в временную папку и только после того, как его переместите в целевой каталог. Это уменьшает окно, в котором могут произойти плохие вещи (но не устраняет их).
  • Если папка является общим ресурсом SMB, есть шанс LockFile даже не работать (некоторые реализации Linux). В этом случае общий подход заключается в том, чтобы иметь файл блокировки, который удаляется после того, как человек, создающий файл, будет выполнен. Проблема с файлом блокировки заключается в том, что если вы забудете удалить его, у вас могут быть проблемы.
  • Вследствие этих осложнений я бы рекомендовал, чтобы получение данных через службу WCF или веб-службу могло быть выгодным, потому что у вас есть намного лучший контроль.

Ответ 7

Фактически, чтобы избежать условий гонки, единственное безопасное решение - повторить попытку.

Если вы сделаете что-то вроде:

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

Вы рискуете другим процессом, прыгающим между защитой while и инструкцией файла процесса. Независимо от того, как выполняется ваше "ожидание доступности файлов", если вы не можете гарантировать, что после разблокировки вы первый процесс доступа к нему, возможно, вы не первый пользователь.

Это более вероятно, что может показаться на первый взгляд, особенно если несколько человек смотрят файл, и, в частности, если они используют что-то вроде наблюдателя файловой системы. Конечно, это еще не особенно вероятно даже тогда...

Ответ 8

Большие ли файлы?

Возможно, вы могли бы попытаться вычислить контрольную сумму 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"));

Ответ 9

Здесь используется цикл 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