FileSystemWatcher на пальцах

  • Михаил
  • 8 мин. на прочтение
  • 70
  • 06 Aug 2022
  • 06 Aug 2022

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

Что такое FileSystemWatcher
FileSystemWatcher— это класс в System.IO пространстве имен, который помогает нам отслеживать изменения файловой системы. Он состоит из различных свойств, которые позволяют нам настраивать типы событий, которые мы хотим прослушивать. Также мы можем применять фильтрацию файлов и каталогов.

Давайте рассмотрим, как настроить FileSystemWatcher в нашем проекте:

public class TextFileManager
{
   private readonly FileSystemWatcher _fileSystemWatcher;
   public TextFileManager(string rootDirectory)
   {
       _fileSystemWatcher = new FileSystemWatcher(rootDirectory);
   }
}

Мы можем инициализировать, FileSystemWatcher просто передав путь, который мы хотим отслеживать. В этой статье мы будем использовать наш TextFileManager класс для настройки и работы с FileSystemWatcher экземпляром. Конечно, вы всегда можете загрузить наш исходный код , чтобы увидеть полную реализацию.

Фильтры FileSystemWatcher
Существует широкий спектр изменений файловой системы, которые мы можем отслеживать с помощью FileSystemWatcher. Однако у нас может быть сценарий, в котором мы не хотим отслеживать все виды изменений в нашей файловой системе. Вместо этого мы хотим отслеживать определенные изменения файлов или определенные типы файлов. Именно здесь фильтры полезны, поскольку они помогают нам сузить тип отслеживаемых изменений. FileSystemWatcher содержит два свойства Filter и NotifyFilter для настройки фильтрации.

Filter это FileSystemWatcher свойство, которое позволяет нам отслеживать определенные файлы, указав шаблон файла. Значение строки фильтра по умолчанию — "*.*" , что означает отслеживать все файлы.

Давайте настроим тип файлов, которые мы хотим отслеживать:

private void ConfigureFilters()
{
   _fileSystemWatcher.Filter = "*.txt";
}

Теперь _fileSystemWatcher отслеживает только изменения текстовых файлов.

NotifyFilter — еще одно свойство, FileSystemWatcher которое позволяет нам указывать и отслеживать определенные изменения в файловой системе. Мы можем настроить NotifyFilter прослушивание нескольких типов изменений с помощью побитового оператора ИЛИ ( "|"). По умолчанию значение NotifyFilter представляет собой побитовую комбинацию ИЛИ LastWrite, DirectoryNameи FileName, но мы можем расширить это:

private void ConfigureFilters()
{
   ...
   _fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes
                               | NotifyFilters.CreationTime
                               | NotifyFilters.DirectoryName
                               | NotifyFilters.FileName
                               | NotifyFilters.LastAccess
                               | NotifyFilters.LastWrite
                               | NotifyFilters.Security
                               | NotifyFilters.Size;
}

Объединяя NotifyFilters перечисления, мы можем расширить диапазон отслеживаемых изменений. NotifyFilters Значения перечисления определяют изменения, которые необходимо отслеживать в файле или каталоге.

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

CreationTime как следует из названия, он позволяет нам отслеживать время создания файла или каталога.

Для отслеживания операций чтения или открытия файла или каталога мы можем использовать LastAccess.

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

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

Мы также можем отслеживать изменения внутри подкаталогов, используя IncludeSubdirectories свойство:

private void ConfigureFilters()
{
   ...
   _fileSystemWatcher.IncludeSubdirectories = true;
   ...
}

События FileSystemWatcher

FileSystemWatcher состоит из 5 различных типов событий, которые мы можем использовать. А именно:  Создано , Удалено , Переименовано, Ошибка и Изменено.

Создание
Мы можем настроить его на запуск события при создании файла или каталога:

private void ConfigureEvents()
{
   _fileSystemWatcher.Created += HandleCreated;
}
private void HandleCreated(object sender, FileSystemEventArgs e)
{
   Console.WriteLine($"Create: {e.FullPath}");
}

Удаление

Мы можем настроить его на запуск события при удалении файла или каталога:

private void ConfigureEvents()
{
   _fileSystemWatcher.Deleted += HandleDeleted;
   ...
}
private void HandleDeleted(object sender, FileSystemEventArgs e)
{
   Console.WriteLine($"Delete: {e.FullPath}");
}

Изменение

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

private void ConfigureEvents()
{
   _fileSystemWatcher.Changed += HandleChanged;
   ...
}
private void HandleChanged(object sender, FileSystemEventArgs e)
{
   Console.WriteLine($"Change: {Enum.GetName(e.ChangeType)} {e.FullPath}");
}

Обработчики событий  Created и Deleted имеют Changed схожие сигнатуры методов.

Переименование

private void ConfigureEvents()
{
   _fileSystemWatcher.Renamed += HandleRenamed;
  ...
}
private void HandleRenamed(object sender, RenamedEventArgs e)
{
   Console.WriteLine($"Rename: {e.OldName} => {e.Name}");
}

Renamed обработчики событий имеют другую сигнатуру метода Created, чем обработчики событий Deleted, и Changed. Второй аргумент типа RenamedEventArgs содержит старое имя и новое имя свойства затронутого файла или каталога.

Ошибки
По разным причинам FileSystemWatcher может достичь состояния, когда он больше не может отслеживать изменения файловой системы по указанному пути. Для запуска события в этом сценарии мы используем Error обработчик событий:

private void ConfigureEvents()
{
   _fileSystemWatcher.Error += HandleError; 
   ...
}
private void HandleError(object sender, ErrorEventArgs e)
{
   Console.WriteLine($"Error: {e.GetException().Message}");
}

Наконец, чтобы разрешить _fileSystemWatcher вызывать события, нам нужно установить EnableRaisingEvents свойство в значение true:

private void ConfigureEvents()
{
   ...
   _fileSystemWatcher.EnableRaisingEvents = true;
}

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

Предостережения FileSystemWatcher
FileSystemWatcher позволяет легко контролировать нашу файловую систему и соответствующим образом запускать события. Однако важно помнить, что при превышении емкости буфера FileSystemWatcher может быть пропущено событие. Размер буфера по умолчанию составляет 8 КБ, но мы можем установить его на любое значение от 4 КБ до 64 КБ с помощью InternalBufferSize свойства. Буфер является хранилищем для всех системных уведомлений, которые относятся к изменениям файлов и исключают имена файлов. Каждое событие может использовать до 16 байт памяти. Если за короткое время происходит множество изменений, это может вызвать переполнение буфера, в результате чего FileSystemWatcher будут пропущены последующие события .

Чтобы избежать переполнения буфера:

  • Минимизируйте типы изменений, которые мы хотим отслеживать, используя NotifyFilterиIncludeSubdirectories
  • Контролируйте только те файлы, которые представляют интерес, указав шаблон файла, и, что еще важнее, избегайте мониторинга файлов с длинными именами, поскольку они вносят большой вклад в заполнение буфера.
  • Чтобы иметь больше места в буфере, увеличьте размер буфера, установив InternalBufferSizeсвойство
  • Сократите код обработчика событий до возможного минимума.

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