В этой статье поговорим о создании файлового роутера File Router, который мониторит заданную папку жесткого диска и перемещает файлы в нужную папку, используя определенный шаблон.
В статье используется код на Visual Basic, а пример с исходными файлами, который вы можете скачать, написан на C#.
Наверняка, у многих есть такая папка, в которой свалены в кучу файлы разных типов: скачанные программы, PDF-документы, фотографии и т.п. И приходится иногда вручную сортировать эти файлы, распихивая их по нужным папкам. Подойдем к этой работе творчески и напишем специальную утилиту.
Утилита File Router действует следующим образом. Программа отслеживает заданную папку на жестком диске и перемещает появившиеся там файлы в нужные папки автоматически по заданному нами алгоритму. Приложение очень простое и легко настраивается.
Будем использовать приложение Windows Form с элементом NotifyIcon. Слежение за папкой будет проводиться при помощи объекта FileSystemWatcher. С его помощью легко отслеживать различные события, например, создание файла, переименование или изменение содержимого.
Наша задача – следить за появлением новых файлов (или переименования) в заданной папке. Когда эти файлы будут обнаружены, их имена сравниваются с заданным выражением. Каждое выражение содержит один или несколько простых шаблонов, разделенных запятыми, например, ".jpg" или "budget." Обратите внимание, что мы используем для шаблона не только расширения файлов, хотя это тоже не возбраняется.
В дополнение к обычной форме, используемой для настроек, проект также содержит такие элементы как NotifyIcon, FileSystemWatcher, FolderBrowserDialog, ToolTip и ContextMenuStrip.
Основная форма отображает настройки. Все настройки будем хранить в объекте FileScannerSettings. Поля в этом объекте определены следующим образом:
Shared SETTINGS_FILENAME As String = "FileRouter.settings"
Dim _activeScan As Boolean = False
Dim _sourcePath As String
Dim _recursiveScan As Boolean = False
Dim _mappings As Dictionary(Of String, FileMapping) =
New Dictionary(Of String, FileMapping)()
ActiveScan определяет, нужно ли следить за заданной папкой. File Router может запускаться по требованию, если это нужно. Словарь Dictionary содержит ключевые слова и значение объекта FileMapping. Каждый FileMapping в свою очередь содержит строковое выражение и путь. Для сохранения настроек мы вызываем метод SaveSettings:
Public Shared Sub SaveSettings(ByVal fs As FileScannerSettings)
Dim str As Stream = File.Open(SETTINGS_FILENAME, FileMode.Create)
Dim bf As BinaryFormatter = New BinaryFormatter
bf.Serialize(str, fs)
str.Close()
End Sub
Мы используем упрощенный вариант сохранения без обработки различных ошибок.
Считывание настроек является обратным процессом:
Public Shared Function GetSettings() As FileScannerSettings
Dim str As Stream = Nothing
Try
str = File.Open(SETTINGS_FILENAME, FileMode.Open)
Dim bf As BinaryFormatter = New BinaryFormatter
Dim fs As FileScannerSettings = _
CType(bf.Deserialize(str), FileScannerSettings)
Return fs
Catch
' Most likely saved file does not exist
Return New FileScannerSettings
Finally
If Not str Is Nothing Then
str.Close()
End If
End Try
End Function
Здесь также используется минимум кода для обработки ошибки. Но это необходимо сделать, потому что файл может не существовать.
Наконец, объект FileScanner сканирует папку и сравнивает файлы. Метод ScanFiles просто получает список файлов из заданного пути и передает его в PerformMatch:
Public Sub ScanFiles()
Dim so As SearchOption
If _settings.RecursiveScan Then
so = SearchOption.AllDirectories
Else
so = SearchOption.TopDirectoryOnly
End If
Dim files() As String =_
Directory.GetFiles(_settings.SourcePath, "*.*", so)
For Each file As String In files
PerformMatch(file)
Next
End Sub
Обратите внимание, что мы можем получать имена файлов только в заданной папке без учета вложенных папок или нужно рекурсивно пройтись по всем подпапкам. Эта опция отражена в объекте FileSystemWatcher, когда приложение находится в активном режиме. Метод PeformMatch сравнивает имена файлов с шаблоном (для удобства переведем имена в нижний регистр) и перемещает файл в нужную папку:
Public Sub PerformMatch(ByVal fileName As String)
Dim fileNameAlone As String = Path.GetFileName(fileName)
Dim fileNameLower As String = fileNameAlone.ToLower()
For Each mapping As FileMapping In _settings.FileMappings.Values
Dim expressions() As String = mapping.Expression.Split(",")
For Each expression As String In expressions
If fileNameLower.Contains(expression) Then
Try
File.Move(fileName, _
Path.Combine( _
mapping.DestinationPath, fileNameAlone))
Return
Catch ex As Exception
RaiseEvent ErrorEncountered(fileNameAlone, ex)
Continue For
End Try
End If
Next
Next
End Sub
Каждый шаблон разбит запятыми. Каждая подстрока затем оценивается методом Contains. Если совпадение найдено, то файл перемещается при помощи метода File.Move. Обратите внимание на собственную обработку ошибок. Сканер файлов может продолжать свою работу, даже если файл имеет ошибку.
Скачать пример
Перевод: Василий Котов