C#: Перебор всех файлов в директории с учетом поддиректорий и отображением текущего файла

Наверное каждый пользовался программами, производящими поиск файла в определенной папке (или сканирование). И каждый знает как это красиво и удобно выглядит, когда можно видеть какой файл просматривается в данный конкретный момент. Сегодня мы поговорим о самом простом варианте реализации данного механизма на языке программирования 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);
            }
        }
Запись опубликована в рубрике C# с метками , , , , , , , . Добавьте в закладки постоянную ссылку.