Мониторинг изменений в директориях и файлах средствами Delphi. Часть #1.Источник: webdelphi
При разработке приложений Delphi для синхронизации чего-либо, например, файлов на разных компьютерах, так или иначе приходится разрабатывать алгоритм с помощью которого можно однозначно определять какие из файлов необходимо удалить из определенной директории, какие переместить, переименовать и т.д. Подобные алгоритмы и примеры их использования на практике не являются редкостью - в Сети Вы можете найти массу самых различных вариаций Delphi-кода с помощью которого можно отследить изменения в директориях и файлах Windows. Не так давно и мне довелось столкнуться с подобной задачей - отследить изменения в определенной директории и сформировать список заданий для синхронизации файлов с сервером. Так как до этого момента мне не доводилось разрабатывать подобные алгоритмы, то пришлось пошерстить просторы Интернета и собрать как можно больше информации на заданную тему. Ну, а результаты моих поисков я решил оформить в виде отдельной статьи в блоге. Итак, сегодняшняя тема - мониторинг изменений в директориях и файлам средствами Delphi. Самым простым и легкодоступным даже для новичков в программировании способом слежения за изменениями в директории является работа по таймеру. Смысл работы заключается в том, что на старте работы программы создается список файлов и поддиректорий в целевой директории. Затем, в момент срабатывания таймера, создается новый список и сравнивается с предыдущим - определяется какие файлы были добавлены, какие удалены/перемещены и т.д. и по уже определенным изменениям проводятся операции синхронизации. Как в данном случае определить, что, скажем, файл Test.txt был изменен? Например, можно рассчитывать каждый раз CRC файла и сравнивать эту сумму с предыдущим значением. Вот исходник функции с www.delphisources.ru, для расчёта CRC файла:
Пример использования функции. Создадим новое приложение в Delphi со следующими компонентами на форме:
Теперь возьмем создадим текстовый файлик и запишем в него строку, скажем "Hello World!", сохраним его, запустим программу и рассчитаем CRC. Вот, что получилось в программе: Теперь снова откроем файл и заменим заглавные буквы на прописные, т.е. строка примет вид "hello world!". Снова рассчитаем CRC: Обратите внимание, что размер файла остался прежним, а содержимое файла изменилось. Это лишний пример того, что использование в качестве критерия изменения файла только его размера - это очень ненадежный вариант и, наверное, даже неправильный. Что можно сказать по поводу предложенного выше варианта мониторинга изменения в директории с помощью таймера? Достоинством этого метода можно назвать его простота. Не важно, какой таймер будет использоваться в работе - стандартный TTimer или собственноручно созданный высокоточный таймер. Повесить обработчик на срабатывание таймера сможет кто угодно. Но наряду с простотой этого варианта он также имеет и массу недостатков. И самый главный из недостатков - ненадежность. Никто не даст Вам гарантий того, что заданный интервал срабатывания таймера будет достаточным для выполнения процедуры обработчика. Как говориться, компьютер пользователя - потёмки. Можно, конечно, задавать большой интервал времени и надеяться на то, что обработчик таймера отработает на 100%, но это всего-лишь "костыль", но никак не решение проблем надежности алгоритма. Кроме того, каждый раз перебирать большое количество файлов - излишняя трата ресурсов. Конечно, в наш век многоядерных процессоров, ресурсы компьютера очень большие, но и разбрасываться ими по поводу и без - не стоит, тем более, если работа ведется над созданием серьезного ресурсоемкого проекта, где на счету каждый байт. И, поэтому, более рациональным способом мониторинга изменений в файлах и директориях является использование функций Windows. Здесь можно выделить два варианта работы:
Оба этих способа в равной степени удобны, но какой из этих способов использовать в конкретной ситуации решать только Вам. Рассмотрим примеры использования функций Windows для мониторинга изменений в директориях.
Использование функций FindFirstChangeNotification, FindNextChangeNotification, FindCloseChangeNotificationПрежде, чем приступим к изучению функций, создадим модуль-заготовку для дальнейшей работы. Следить за изменениями мы будем в потоке (TThread):
Теперь рассмотрим назначение функций Windows. FindFirstChangeNotification - создает дескриптор уведомления об изменениях и устанавливает начальные условия отправки уведомления. Функция возвращает дескриптор (THandle) либо INVALID_HANDLE_VALUE в случае ошибки:
lpPathName: PChar - полный путь к директории за которой проводится слежение. Значение этого параметра не может содержать относительный путь или пустую строку.
FindNextChangeNotification - указывает, чтобы операционная система вернула сигнал уведомления об изменении THandle в следующий раз, когда обнаруживаются изменения, согласно фильтру, установленному функцией FindFirstChangeNotification .
hChangeHandle: THandle - дескриптор, полученный с помощью функции FindFirstChangeNotification . FindCloseChangeNotification - останавливает мониторинг изменений в директории.
hChangeHandle: THandle - дескриптор, полученный с помощью функции FindFirstChangeNotification . Назначение функций теперь более или менее стали нам понятны - осталось закрепить полученные знания на опыте. Итак, прежде всего наш поток должен получать два значения: путь к директории за которой мы будем следить и флаг, указывающий следует ли мониторить подкаталоги. Пишем конструктор потока:
Теперь создадим следующий Execute:
В приведенном выше обработчике Execute мы проводим мониторинг изменения имени файла/директории или размера файла. При этом мы ожидаем любого из заданных в фильтре событий и выводим сообщение. Кстати, создадим событие для вывода сообщения об изменениях, например, такое:
Теперь всё готово для проверки работоспособности нашего потока. Создадим новый проект Delphi и на главную форму положим следующие компоненты: В uses подключим модуль с нашим потоком и объявим следующую переменную:
Теперь напишем необходимые обработчики для событий:
Запускаем программу, выбираем директорию за которой необходимо следить и нажимаем кнопку "Следить". Теперь попробуем скопировать/удалить какой-нибудь файл и увидим в Memo соответствующее сообщение. Можете накачать электронные книги бесплатно и слить в директорию сразу кучу текстовых файлов - поток корректно сообщит Вам об изменениях каталога ровно столько раз сколько файлов Вы сбросите в директорию. |