Наверное каждый пользовался программами, производящими поиск файла в определенной папке (или сканирование). И каждый знает как это красиво и удобно выглядит, когда можно видеть какой файл просматривается в данный конкретный момент. Сегодня мы поговорим о самом простом варианте реализации данного механизма на языке программирования C#.
Создадим пустой WinForm проект. Добавим в форму четыре элемента: две кнопки (button), текстовое поле (textbox), текст (label).
Оставим имена контроллов по умолчанию. Запретим редактирование текстового поля (textBox1.Enabled = false), назначим текст одной кнопки «Обзор» (button1.Text = «Обзор»), и текст второй кнопки «Старт» (button2.Text = «Старт»).
Теперь щелкним два раза на кнопку и зададим ей событие по клику, которое будет показывать нам обзор директорий для выбора нужного пути.
private void button1_Click(object sender, EventArgs e) { FolderBrowserDialog FBD = new FolderBrowserDialog(); if (FBD.ShowDialog() == DialogResult.OK) { textBox1.Text = FBD.SelectedPath; } }
Дальше мы будем делать простой прогон по всем файлам в выбранной директории (с учетом подкаталогов). Данное действие мы повесим на событие нажатия на кнопку «Старт». Реализовывать просмотр всех подкаталогов мы будем рекурсивно, поэтому код, отвечающий за просмотр файлов мы вынесем в отдельную функцию. Назовем ее FileSearchFunction. Главное что стоит учесть в данной функции это просмотр нужно делать как в глубь каталога, так и в ширину. «В ширину» в данном случае будет подрузомевать просмотр файлов, «В глубь» — просмотр папок. Причем делать нужно сначала что-то одно, потом другое, при этом порядок не важен. Остановимся на варианте: Сначала идем в самую глубокую папку, потом просматриваем файлы. Имеем:
private void FileSearchFunction(string Dir) { System.IO.DirectoryInfo DI = new System.IO.DirectoryInfo(Dir); System.IO.DirectoryInfo[] SubDir = DI.GetDirectories(); for (int i = 0; i < SubDir.Length; ++i) this.FileSearchFunction(SubDir[i].FullName); System.IO.FileInfo[] FI = DI.GetFiles(); for (int i = 0; i < FI.Length; ++i) label1.Text = FI[i].FullName; }
Теперь повесим событие на кнопку "Старт".
private void button2_Click(object sender, EventArgs e) { if (textBox1.Text != String.Empty && System.IO.Directory.Exists(textBox1.Text)) this.FileSearchFunction(textBox1.Text); }
Если мы сейчас запустим наше приложение, выберем папку и нажмем "Старт", то мы немного разочаруемся. Во первых, наша форма зависнет до тех пор, пока не отработает наша функция, а следовательно мы не видим текущий просматрвиваемый файл. Во-вторых, путь к файлу может быть слишком большой и он просто не уместится в наш label. Для решения первой проблемы достаточно нашу функцию вызывать в потоке. Однако стоит помнить, что мы производим изменение элемента формы, поэтому без Invoke в функции не обойтись. Вторая проблема решается с помощью дополнительной проверки длины строки пути файла и ее укорачивания. Так же возможна ситуация, когда папка будет недоступна, здесь на помощь приходит технология try-catch. Имеем:
private void FileSearchFunction(object Dir) { System.IO.DirectoryInfo DI = new System.IO.DirectoryInfo((string)Dir); System.IO.DirectoryInfo[] SubDir = null; try { SubDir = DI.GetDirectories(); } catch { return; } for (int i = 0; i < SubDir.Length; ++i) this.FileSearchFunction(SubDir[i].FullName); System.IO.FileInfo[] FI = DI.GetFiles(); for (int i = 0; i < FI.Length; ++i) this.Invoke(new System.Threading.ThreadStart(delegate { if (FI[i].FullName.Length > 40) label1.Text = "..." + FI[i].FullName.Substring(FI[i].FullName.Length - 40); else label1.Text = FI[i].FullName; })); } private void button2_Click(object sender, EventArgs e) { if (textBox1.Text != String.Empty && System.IO.Directory.Exists(textBox1.Text)) { System.Threading.Thread T = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(FileSearchFunction)); T.Start(textBox1.Text); } }