Как мне опросить большое количество файлов на предмет изменений? - PullRequest
8 голосов
/ 26 августа 2011

Я бы хотел опросить файловую систему на предмет любых измененных, добавленных или удаленных файлов или подкаталогов. Все изменения должны быть обнаружены быстро, но без давления на машину. ОС - Windows> = Vista, наблюдаемая часть - локальный каталог.

Как правило, я бы прибегнул к FileSystemWatcher, но это привело к проблемам с другими программами, которые пытались наблюдать то же место (в частности, Windows Explorer). Кроме того, я слышал, что FSW не очень надежен даже для локальных папок и с большим буфером.

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

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

Мне интересно, есть ли шаблоны для такого рода проблем, или если у кого-то есть опыт в этой ситуации.

Ответы [ 3 ]

3 голосов
/ 26 августа 2011

Мы реализовали аналогичную функцию, используя C #. FileSystemWatcher был неэффективен с большими деревьями каталогов.

В качестве альтернативы мы использовали FSNodes, созданную нами структуру, используя следующие вызовы Windows API:

    [StructLayout(LayoutKind.Sequential)]
        private struct FILETIME
    {
        public uint dwLowDateTime;
        public uint dwHighDateTime;
    };

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
        private struct WIN32_FIND_DATA
    {
        public FileAttributes dwFileAttributes;
        public FILETIME ftCreationTime;
        public FILETIME ftLastAccessTime;
        public FILETIME ftLastWriteTime;
        public uint nFileSizeHigh;
        public uint nFileSizeLow;
        public int dwReserved0;
        public int dwReserved1;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)]
        public string cFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_ALTERNATE)]
        public string cAlternate;
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool FindClose(IntPtr hFindFile);

    [DllImport("kernel32", CharSet=CharSet.Unicode)]
    private static extern IntPtr FindFirstFile(
        string lpFileName, out WIN32_FIND_DATA lpFindFileData);

    [DllImport("kernel32", CharSet=CharSet.Unicode)]
    private static extern bool FindNextFile(
        IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);

То, что мы делаем, это статическая обработка. Мы сохраняем дерево метаданных на диске и сравниваем хранимое дерево каталогов с загруженным, ища измененное (на основе его метки времени (быстрее) или хеша файла). Кроме того, мы можем управлять удаленными, добавленными и перемещенными, даже перемещенными, измененными файлами (также на основе хэша файла).

Эта реализация, смешанная с демоном, который выполнял ее каждый POLL_TIME, была для нас действительной. Надеюсь, это поможет.

1 голос
/ 03 сентября 2011

Лучше всего использовать журнал USN, если он локальный, у вас есть права администратора, а разделы - NTFS. Журнал USN чрезвычайно быстрый и надежный. Это длинная тема, и эта ссылка объясняет все: http://www.microsoft.com/msj/0999/journal/journal.aspx

0 голосов
/ 26 августа 2011

Для * nix-сред вы можете использовать inotify https://github.com/rvoicilas/inotify-tools/wiki/,, который отлично работал в моих ограниченных исследованиях.Там может быть версия, которая работает с окнами, с которой у меня меньше опыта ... быстрое приближение к Google привело меня к java-клону под названием jnotify http://jnotify.sourceforge.net/, который объявлен для работы на окнах, так что, возможно, стоит попробовать.

...