Поиск файлов в Delphi

Рассмотрим следующий пример:

 

FindFirst— открывает поиск. В качестве первого параметра выступает маска поиска. Если вы укажете конкретный файл, то система найдет именно его. Вы так­же можете искать и целые группы файлов. Например, можно запустить поиск всех файлов в корневом каталоге диска С:. Для этого первый параметр должен быть оп­ределен как— 'с: \ *. *'. Для поиска только ЕХЕ-файлов, в папке Fold вы должны указать — 'с: \Fold\ * . ехе'.

Второй параметр — атрибуты, используемые при поиске файлов. Чтобы искать любые файлы, нужно указать faAnyFiie. Помимо этого, можно искать по следую­щим атрибутам:

  • faReadOnly — искать файлы с атрибутом Readonly (только для чтения);
  • faHidden — искать скрытые файлы;
  • faSysFile — искать системные файлы;
  • faArchive — искать архивные файлы;
  • faDirectory — искать папки.

Последний параметр— это структура, в которой нам вернется информация о поиске, а именно: имя найденного файла, размер, время создания и т. д.

После вызова этой процедуры, мы должны проверить на корректность найден­ный файл. Если результат равен invalid_handle_value, то функция не нашла ни одного файла. Если все нормально и файл, удовлетворяющий критериям поиска, существует, то запускается цикл Repeat.. .until.

 

Мы уже рассматривали циклы, но все же повторимся и вспомним их работу. Цикл выполняет операторы, расположенные между repeat и until, пока условие, расположенное после слова until, выполняется. Как только условие нарушается, цикл прерывается.

 

Здесь надо заметить, что функция поиска возвращает через параметр Информация имена файлов и может вернуть нам в качестве имени точку или две точки. Если вы посмотрите на папку, то таких файлов не будет. Откуда берутся эти имена? Имя файла в виде точки указывает на текущую папку, а имя файла из двух точек указы­вает на папку верхнего уровня. Если мы встречаем такие имена, то их нужно про­сто отбрасывать.

 

Параметр Информация имеет тип структуры TSearchRec. Давайте рассмотрим ее подробнее. Объявление выглядит так:

 

 

Функция FindNext заставляет найти следующий файл, удовлетворяющий пара­метрам, указанным в функции FindFirst. Этой функции нужно передать структуру searchRec, по которой будет определено, на каком месте сейчас остановлен поиск, и с этого момента он будет продолжен. Как только будет найден новый файл, функция вернет в структуре SearchRec информацию о новом найденном файле.

 

Функция Findciose закрывает поиск. В качестве единственного параметра нуж­но указать все ту же структуру SearchRec.

 

Давайте напишем какой-нибудь реальный пример, который наглядно покажет работу с функциями поиска файлов. Посмотрите на структуру TSearchRec. Как ви­дите, она умеет возвращать размер найденного файла. Вот и тема для примера — мы напишем код, который будет определять размер указанного файла.

 

Создайте новый проект и установите на форму два компонента TEdit и одну кнопку. Можете еще украсить все это текстом. У вас должно получиться нечто по­хожее на рис. 10.4.

По нажатии кнопки (событие onclick) напишите следующий код:

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

 

Итак, для примера нам понадобятся на форме два поля ввода с именами:

  • edLookFor — в нем будут вводить имя файла, который нужно найти;
  • edLookin — диск или путь к папке, где нужно искать, включая вложенные папки. Нам также понадобятся кнопка, по нажатии которой будет происходить скани­рование, и поле ввода Memo, куда будет выводиться результат, ведь файл с одним и тем же именем может быть в нескольких папках.

По нажатии кнопки пишем следующий код:

Memo1.Lines.Clear; ScanFolder(edLookin.Text);

В первой строке очищаем поле Memo от предыдущих результатов. После этого запускается функция ScanFolder, которой передаем путь, где искать файл. Код этой функции можно увидеть в листинге 10.18, а объявление ее должно быть в раз­деле private вашей формы в следующем виде: 

 

В первой же строке запускаем поиск с помощью функции FindFirst. В качестве первого параметра передается папка плюс маска Vs.*'. Второй параметр равен faAnyFile, чтобы функция искала для нас все файлы любого типа. Последний па­раметр — это структура TSearchRec, через которую мы будем получать результат. Если файл найден, то проверяем, если имя равно точке или двум точкам, то про­должаем поиск дальше.

 

После этого в переменную FileName помещаем полный путь найденного файла. Для этого используем функцию SlashSep. Эта функция не существует в Delphi, мы должны сами ее написать:

 

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

 

Вернемся к листингу 10.18. На следующей стадии идет проверка, что именно мы нашли — файл или папку. Если это папка, то нужно поискать файл внутри нее. Для этого мы вызываем ScanFolder, указывая вложенную папку. Но мы же уже нахо­димся в этой функции, получается, что функция будет вызывать сама себя? Пра­вильно — это и есть рекурсия. Мы снова вызываем ScanFolder с указанием вло­женной папки, и этот вызов будет продолжаться, пока все папки не будут просканированы.

 

Если мы нашли не папку, то проверяем имя файла. Если оно совпадает с иско­мым, то выводим соответствующее сообщение в Memo компонент. Итак, поиск про­должается до тех пор, пока не переберем все файлы.

 

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

if FindFirst(SlashSep(Folder, sr.Name), faAnyFile, sr) = 0 then

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

В качестве строки поиска можно указывать и маски, например, следующая строка ищет все INI-файлы в корне диска С:

if FindFirst(' с:*.ini', faAnyFile, sr) = 0 then

Но когда вы указываете конкретный файл, то функция не будет возвращать пап­ки. Как решить эту проблему? Попробуйте подумать сами. Есть достаточно эле­гантное решение.

 

dle

Помоги проекту! Расскажи друзьям об этом сайте: