Windows: Как определить, был ли файл изменен с указанной даты

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

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

  1. Пользователь обрабатывает каталог в 9:00.
  2. Затем файл копируется из этого каталога и изменяется так, чтобы он имел дату последнего изменения 9:30.
  3. Затем каталог обрабатывается снова в 10:00.
  4. Измененный файл затем копируется обратно в каталог в 10:30
  5. Наконец каталог снова обрабатывается в 11:00

Поскольку дата изменения данного файла - 9:30, а каталог был последний раз обработан в 10:00, файл пропускается, когда этого не должно быть.

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

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

5 ответов

Решение

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

Возможно, вы захотите посмотреть на использование класса FileSystemWatcher. Этот класс позволяет отслеживать каталог на наличие изменений и запускать событие, когда что-то изменяется. Ваш код может обработать событие и обработать файл.

Из MSDN:

// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = args[1];
/* Watch for changes in LastAccess and LastWrite times, and
   the renaming of files or directories. */
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
   | NotifyFilters.FileName | NotifyFilters.DirectoryName;
// Only watch text files.
watcher.Filter = "*.txt";

// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);

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

Рассматривали ли вы добавление процесса для просмотра вашего каталога вместо? Используя FileSystemWatcher? Затем вы переходите от использования пакетного процесса и системы реального времени для мониторинга ваших файлов.

Как вы уже заметили, при копировании файла в существующий конечный файл сохраняется CreationTime существующего файла, и для LastWriteTime устанавливается значение LastWriteTime исходного файла, а не текущее системное время при выполнении копирования. Два возможных решения:

  1. Выполните удаление и копирование, убедившись, что целевое CreationTime будет текущим временем системы.
  2. Также проверьте наличие в файле атрибута Rchived и очистите его во время обработки. При копировании source->dest, dest +A будет установлен атрибут.
Другие вопросы по тегам