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

Файлы мониторинга - как узнать, когда файл завершен

У нас есть несколько приложений .NET, которые контролируют каталог для новых файлов, используя FileSystemWatcher. Файлы копируются из другого места, загружаются через FTP и т.д. Когда они входят, файлы обрабатываются так или иначе. Тем не менее, одна из проблем, на которые я никогда не видел удовлетворительного ответа, - это: для больших файлов, как узнать, когда файлы, на которые ведется наблюдение, все еще записываются? Очевидно, нам нужно подождать, пока файлы не будут завершены и закрыты, прежде чем мы начнем их обрабатывать. Событие args в событиях FileSystemWatcher, похоже, не затрагивает это.

4b9b3361

Ответ 1

Вы пытались получить блокировку записи в файле? Если это будет написано, это должно потерпеть неудачу, и вы знаете, чтобы оставить его в покое немного...

Ответ 2

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

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

Ответ 3

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

Ответ 4

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

Я использовал метод блокировки для отправки больших файлов по FTP в прошлом.

Файл отправляется с альтернативным расширением и переименовывается после того, как отправитель счастлив, что он есть.

Вышеупомянутое, очевидно, сочетается с процессом, который периодически подбирает старые файлы с временным расширением.

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

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

Проверка файлов, которые не были изменены за x минут, подвержена всевозможным проблемам.

Ответ 5

Следующий метод пытается открыть файл с разрешениями на запись. Он заблокирует выполнение, пока файл не будет полностью записан на диск:

/// <summary>
/// Waits until a file can be opened with write permission
/// </summary>
public static void WaitReady(string fileName)
{
    while (true)
    {
        try
        {
            using (System.IO.Stream stream = System.IO.File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                if (stream != null)
                {
                    System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} ready.", fileName));
                    break;
                }
            }
        }
        catch (FileNotFoundException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        catch (IOException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        catch (UnauthorizedAccessException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        Thread.Sleep(500);
    }
}

(из моего ответа на связанный вопрос)

Ответ 6

Вам, вероятно, придется пойти с некоторой внеполосной сигнализацией: продюсер "file.ext" напишет фиктивный файл "file.ext.end".

Ответ 7

+1 для использования сигнального файла file.ext.end, если это возможно, где содержимое file.ext.end является контрольной суммой для более крупного файла. Это не для безопасности, так как это означает, что на этом пути ничего не исказилось. Если кто-то может вставить свой собственный файл в большой поток, они также могут заменить контрольную сумму.

Ответ 8

Блокировка записи не помогает, если загрузка файла завершилась неудачно, и отправитель еще не пробовал переадресацию (и повторное удаление) файла.

Ответ 9

То, как я проверяю Windows, если файл полностью загружен ftp, - это попытаться переименовать его. Если переименование не выполняется, файл не завершен. Не очень элегантный, признаюсь, но он работает.