Delphi выбор файлов по маске

Обновлено: 07.07.2024

Вот примерно что у меня есть пока

procedure Search1(PPath:string);
var
pj:integer;
begin
with Frm_Main do
begin
if FindFirst(PPath + '\*.*', faAnyFile, sr) = 0 then
begin
repeat
if ((sr.Name<>'.') and (sr.Name<>'..')) then
if (sr.Attr=faDirectory) then
Search1(PPath + '\' + sr.Name)
else
if AnsiLowerCase(ExtractFileExt(sr.Name)) = '.txt' then
begin
pj :=
Operate_PetrovAM_FilePlaceType(1, Unit_ServerName, Unit_BaseName, sr.name, PPath);
TakeDOCsFromTXT('1', pj, adress_elements,PPath + '\' + sr.name);
end;
until FindNext(sr) <> 0;
FindClose(sr);
end; then
end;
end;

procedure EnumFolder(const AFolderName: string);
var
BackFolder: string;
FindFile: Integer;
SearchRec: TSearchRec;

GetDir(0, BackFolder);
ChDir(AFolderName);

FindFile:=FindFirst('*.*', faAnyFile, SearchRec);
while FindFile = 0 do
begin
with SearchRec do
if (Name <> '.') and (Name <> '..') then
if (Attr and faDirectory) <> 0 then
EnumFolder(Concat(AFolderName, '\', Name))
else
LoadPacket(Concat(AFolderName, '\', Name));

FindFile:=FindNext(SearchRec);
end;
FindClose(SearchRec);

Posted via ActualForum NNTP Server 1.4

ненавижу таких людей
когда человек спрашивает совета, а ему в ответ "Гугли"
ты держись там, всего доброго, хорошего настроения и здоровья

ты еще бы ссылок бестолковых накидал - мол туда сходи, там посмотри, там мол что-то похожее делалось - в итоге человек запутывается еще больше

ненавижу таких людей
когда человек спрашивает совета, а ему в ответ "Гугли"
ты держись там, всего доброго, хорошего настроения и здоровья

ты еще бы ссылок бестолковых накидал - мол туда сходи, там посмотри, там мол что-то похожее делалось - в итоге человек запутывается еще больше

ненавижу таких людей
когда человек спрашивает совета, а ему в ответ "Гугли"
ты держись там, всего доброго, хорошего настроения и здоровья

ты еще бы ссылок бестолковых накидал - мол туда сходи, там посмотри, там мол что-то похожее делалось - в итоге человек запутывается еще больше

НУ ничего себе, братишка, спасибо большое! Чтобы я бы без твоего совета делал?
От души! Мегареспект! Вот именно без этого совета я бы вообще не знал как дальше жить!

В этом уроке мы с вами ознакомимся с основными принципами программной организации поиска файлов. Для начала определимся, зачем нам это может быть нужно. Например, вам нужно при запуске программы на выполнение просканировать определенный каталог на присутствие DOC файлов, и при наличии таковых открыть их на редактирование или напечатать. А как вам такая идея: фоновый поиск EXE файла в сети, и при обнаружении новой версии, автоматическое обновление.


Многим известны программы, где можно искать файлы, правила поиска файла. Файлы можно искать как с файловых командирах (нортон, волков, дос навигатор, фар), так в любой операционной системе. В операционной системе windows диалоговое окно поиска файла вызывается "Пуск" - "Поиск" - "Файлы и папки". В открывшимся окне необходимо задать условие искомого файла (название, маска) и путь начального поиска (каталог). На других вкладках этого диалогового окна можно расширить возможности поиска по дате изменения, по содержащемуся тексту, по размеру.

Вспомним правила поиска файлов. Вы можете задать как имя искомого файла, так и его маску, если название неизвестно или необходимо найти несколько. Т.е. применяя специальный шаблон поиска, вы можете организовать условия выборки найденных файлов. Сразу оговорюсь, что поиск можно применять как к файлам, так и к каталогам. Будем их называть элементами файловой системы. В шаблон маски искомых элементов может входить:
1. Буквы и цифры в названии и расширении.
2. Символ * (звездочка, математический знак "умножить"), заменяющий любое количество всевозможных букв и цифр в названии или расширении.
3. Символ ? (знак вопроса), заменяющий одну букву или цифру в названии или расширении искомого элемента.
Например, вы ищите все текстовые файлы с расширением TXT. В поле имени искомого файла вам нужно ввести "*.TXT" (пишется без кавычек) и система найдет все такие файлы в указанном диске или каталоге. Если вам надо найти все файлы с названием semen, то в поле поиска файла нужно ввести "semen.*". Если вам нужно найти элементы с третьей буквой k и с первой буквой t в расширении, то вводите "??k*.t*". Здесь знак вопроса указывает на любой символ, третьим символом по порядку идет буква k, далее название файла (каталога) может состоять из любого количества букв и цифр, указываем звездочку. В расширении первая буква t, дальше следует любое расширение.
Примечание: файлы и каталоги в операционной системе windows ищутся без учета регистра, т.е. строчние и прописные буквы не различаются.

Теперь рассмотрим программный поиск файлов с помощью языка программирования object pascal.

Вся организация цикла поиска, а именно это и есть цикл с продолжением поиска, сводится к:
1. Задание условий поиска. Это каталог и маска искомого элемента или элементов, атрибуты элемента(ов). При задании условий поиска сразу происходит поиск первого подходящего под условие. Это функция FindFirst.
2. Продолжение поиска следующего элемента по заданным в первом пункте условиям. Это функция FindNext и она может вызываться сколько угодно раз, пока все файлы и каталоги, удовлетворяющие условию, не будут найдены.
3. Закрытие поиска и освобождение памяти, выделяемую системой под поиск. Команда FindClose.

FindFirst (КАТАЛОГ_ПОИСКА_И_МАСКА_ФАЙЛА , АТРИБУТЫ_ИСКОМОГО_ФАЙЛА , ПОИСКОВОЯ_ПЕРЕМЕННАЯ);

где: Каталог для поиска и маска искомого элемента - строковая величина, имеющая тип String, может, например, содержать 'c:\*.*' - все элементы в корне диска С. Обратите внимание, что указывается полный путь для поиска.

Атрибуты искомого элемента это пользовательские или системные атрибуты, которые может иметь файл (каталог, метка диска). Вот их перечень:
faReadOnly - Файлы "только чтение". Такой атрибут устанавливается на файлы, которые не рекомендовано изменять, удалять. Такой атрибут имеют файлы, например, записанные на компакт-дисках.
faHidden - Скрытые файлы. При обычных установках браузера и командира эти файлы невидимы.
faSysFile - Системные файлы.
faVolumeID - Файл метки диска. Такой элемент в своем имени имеет название диска (максимум 11 символов).
faDirectory - Атрибут признака каталога.
faArchive - Обычный файл. По умолчанию устанавливается на заново создаваемых файлах.
faAnyFile - Если установить в качестве атрибута искомых элементов, то будет произведен поиск по всем вышесказанным атрибутам.
Эти вам нужно искать только элементы, имеющие атрибут "каталог" и "скрытый", то можно применить знак математического сложения, например faDirectory + faHidden.

Поисковая переменная имеет тип TSearchRec. В нее, при успешном результате поиска, будет занесены все необходимые данные о найденном файловом элементе.

Поскольку FindFirst является функцией, то она должна сама возвращать некоторое значение. Это значение имеет тип Integer и означает результат поиска файла (код ошибки поиска). Если файл найден, то принимает нулевое значение.

Эта функция продолжает поиск, заданный в функции FindNext. Возвращает значение результата поиска (нулевое в случае успешного поиска).

Закрывает поиск и освобождает память, выделенную системой под поиск.

Теперь рассмотрим пример. Допустим, нам надо найти все файлы и каталоги в каталоге DELPHI, находящийся на диске C:. В дальнейшем, вы можете самостоятельно, изменяя маску, менять условия поиска. Для формы с компонентом ListBox1 и кнопкой Button1 реакция на OnClick по кнопке:

procedure TForm1.Button1Click(Sender: TObject);
Var SR:TSearchRec; // поисковая переменная
FindRes:Integer; // переменная для записи результата поиска
begin
ListBox1.Clear; // очистка компонента ListBox1 перед занесением в него списка файлов

FindRes:=FindFirst('c:\delphi\*.*',faAnyFile,SR); // задание условий поиска и начало поиска

While FindRes=0 do // пока мы находим файлы (каталоги), то выполнять цикл
begin
ListBox1.Items.Add(SR.Name); // добавление в список название найденного элемента
FindRes:=FindNext(SR); // продолжение поиска по заданным условиям
end;
FindClose(SR); // закрываем поиск
end;

Представленный пример кода, в принципе, является основой для организации более углубленного поиска, поиска файлов по времени создания, по содержащимся словам. Если вы запустите эту программу на выполнение, то при нажатии на кнопку Button1 вы увидите в списке в первой и второй строке элементы "." и "..". Это элементы, имеющие атрибут "каталог". Первый содержит связь с корневым каталогом диска, второй содержит связь к каталогом верхнего уровня. Со вторым вы встречаетесь в дисковых командных оболочках, например нортон, когда выбираете каталог ".." и нажимаете на "ввод". Тем самым вы попадаете в каталог на уровень выше. Естественно, в нашей поисковой программе такие элементы не надо вносить в список, поэтому мы игнорируем их нахождение. Исправляем процедуру нажатия на кнопку Button1:

procedure TForm1.Button1Click(Sender: TObject);
Var SR:TSearchRec;
FindRes:Integer;
begin
ListBox1.Clear;

FindRes:=FindFirst('c:\delphi\*.*',faAnyFile,SR);
While FindRes=0 do
begin
if ((SR.Attr and faDirectory)=faDirectory) an d // если найденный элемент каталог и
((SR.Name='.')or(SR.Name='..')) then // он имеет название "." или "..", тогда:
begin
FindRes:=FindNext(SR); // продолжить поиск
Continue; // продолжить цикл
end;

ListBox1.Items.Add(SR.Name);
FindRes:=FindNext(SR);
end;
FindClose(SR);
end;

В этом случае, при нахождении каталога с именем "." или с именем ".." программа продолжит обработку цикла поиска без вывода найденного имени элемента в компонент списка ListBox1.

Теперь рассмотрим тип TSearchRec. Он имеет в себе несколько полезных свойств:
Name - название найденного каталога (файла);
Size - размер файла в байтах;
Attr - атрибуты каталога (файла);
Time - упакованное значение времени и даты создания каталога (файла).

Все вышеперечисленные свойства мы уже рассмотрели или они понятны сразу, за исключением свойства Time. Оно имеет тип Integer и содержит в себе упакованное значение даты и времени создания файла. Распаковка производится с помощью функции FileDateToDateTime, которая в результате возвращает значение даты и времени.
Теперь добавим в нашу форму компонент DateTimePicher1 (страница Win32) и допишем несколько строк.

procedure TForm1.Button1Click(Sender: TObject);
Var SR:TSearchRec;
FindRes:Integer;
begin
ListBox1.Clear;

FindRes:=FindFirst('c:\delphi\*.*',faAnyFile,SR);
While FindRes=0 do
begin
if ((SR.Attr and faDirectory)=faDirectory) and
((SR.Name='.')or(SR.Name='..')) then
begin
FindRes:=FindNext(SR);
Continue;
end;
if FileDateToDateTime(SR.Time) // если у файла (каталога) дата создания меньше, чем установлено в DateTimePicker1, то
begin
FindRes:=FindNext(SR); // продолжить поиск
Continue; // продолжить цикл
end;

ListBox1.Items.Add(SR.Name);
FindRes:=FindNext(SR);
end;
FindClose(SR);
end;

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

Теперь попробуем организовать поиск файлов во всех вложенных каталогах. Это не так просто, как может показаться на первый взгляд. Нам придется вручную организовывать весь цикл входа-выхода из каталога, перебор файлов. Немного сложноватый материал, но возможно те из вас, кто уже работал с языком программирования pascal или другим, знакомы с технологией многократности и многовложенности использования одного и того же программного кода. Коротко объясню алгоритм работы такой программы.
1. Задание начальных условий поиска, поиск первого элемента.
2. Если найден файл, то выводим его и соответственно обрабатываем (выводим в список, открываем, удаляем и т.п.).
3. Если найден каталог, то начинаем новую процедуру поиска. Но программный код остается прежним. Мы просто заново вызываем и входим в эту же процедуру поиска.
4. Обрабатываем таким же образом все вложенные в этот каталог файлы и каталоги (начинаем новый поиск в обнаруженном каталоге).
5. Если элементов во вложенном каталоге больше нет, то обработка процедуры поиска в нем завершается, и мы выходим из нее. При этом мы оказываемся в том же месте, откуда и вызвали эту процедуру. Но она была вызвана из этой же процедуры. Поэтому программа продолжает свое выполнение дальше с момента возврата.
Таким образом, сколько витков программа наматывает на так называемый клубок, столько витков она и размотает. Программа на выполнении проходит все дерево вложенных каталогов, выполняя один и тот же кусок программного кода! И при этом данные условий поиска не перепутываются, и для каждой уникальной процедуры они сохраняются.

Рассмотрим пример. Создайте новый проект. Для создания отдельной процедуры поиска нам нужно объявить ее в соответствующем разделе (создаем ее вручную, поэтому и самостоятельно объявляем).

В разделе public пишем строку:

А в разделе кода программы, до слова "end." вставляем пустой каркас процедуры

procedure TForm1.FindFile(Dir:String);
begin

На форму вставляем компонент списка ListBox1, Button1, Edit1. Для компонента Edit1 свойство Text устанавливаем в "c:\delphi\". Обратите внимание на последний символ, знак "\", присутствие которого в начальном пути поиска обязательно. Дальше процедура OnClick для кнопки Button1 выглядит следующим образом:

procedure TForm1.Button1Click(Sender: TObject);
begin
ListBox1.Clear; // очистка списка файлов
FindFile(Edit1.Text); // поиск файлов с начальными условиями, заданных в Edit1
end;

Созданная нами вручную процедура поиска:

procedure TForm1.FindFile(Dir:String);
Var SR:TSearchRec;
FindRes:Integer;
begin
FindRes:=FindFirst(Dir+'*.*',faAnyFile,SR);
While FindRes=0 do
begin
if ((SR.Attr and faDirectory)=faDirectory) and
((SR.Name='.')or(SR.Name='..')) then
begin
FindRes:=FindNext(SR);
Continue;
end;

if ((SR.Attr and faDirectory)=faDirectory) then // если найден каталог, то
begin
FindFile(Dir+SR.Name+'\'); // входим в процедуру поиска с параметрами текущего каталога + каталог, что мы нашли
FindRes:=FindNext(SR); // после осмотра вложенного каталога мы продолжаем поиск в этом каталоге
Continue; // продолжить цикл
end;

ListBox1.Items.Add(SR.Name);
FindRes:=FindNext(SR);
end;
FindClose(SR);
end;

Если вы в компоненте Edit1 в качестве начального условия поиска файлов зададите корневую папку диска, например "С:\", то вы получите полный перечень всех файлов на данном диске. Обратите внимание на скорость поиска файлов и скорость работы вашей программы.

Диалоговые окна выбора имени файла используются в процессах открытия и сохранения файла. Часто эти диалоги называют также диалогами открытия/сохранения файла, хотя на самом деле они позволяют только выбрать имя файла, а все действия по открытию или сохранению файла программируются вручную.

Компонент OpenDialog реализует диалог открытия файла. При запуске этого диалога появляется окно (см. скриншот), в котором можно выбрать имя открываемого файла. В случае успешного закрытия диалогового окна (нажатием кнопки Open) в качестве результата возвращается выбранное имя файла.


Компонент SaveDialog предлагает стандартный диалог сохранения файла, который отличается от диалога открытия файла только своим заголовком.

Основные свойства компонентов OpenDialog и SaveDialog

Далее перечислены основные свойства компонентов OpenDialog и SaveDialog.

FileName типа String — указывает имя и полный путь файла, выбранного в диалоге. Имя файла отображается в строке редактирования списка Имя файла и является результатом диалога.

Title типа String— задает заголовок окна. Если свойство Title не установлено, то по умолчанию используется заголовок Open для OpenDialog и заголовок Save — для SaveDialog.

InitiaLDir типа String— определяет каталог, содержимое которого отображается при вызове диалогового окна. Если каталог не задан, то отображается содержимое текущего каталога.

DefaultExt типа String — задает расширение, автоматически используемое в имени файла, если пользователь не указал расширение.

Filter типа String— задает маски имен файлов, отображаемых в раскрывающемся списке Тип файлов. В диалоговом окне видны имена файлов, совпадающие с указанной маской (см. скриншот) это файл с расширением jpeg). По умолчанию значением Filter является пустая строка, что соответствует отображению имен файлов всех типов.

FilterIndex типа Integer — указывает, какая из масок фильтра отображается в списке. По умолчанию свойство FilterIndex имеет значение 1 (используется первая маска).

Options

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

Основные параметры свойства Options

  • ofAllowMultiSelect (из списка можно выбрать одновременно более одного файла);
  • ofCreatePrompt (при вводе несуществующего имени файла выдается запрос на создание файла);
  • ofNoLongNames (имена файлов отображаются как короткие, не более 8 символов для имени и 3 символов для расширения);
  • ofOldStyleDialog (создает диалоговое окно в стиле Windows 3.11).

Фильтр представляет собой последовательность значений, разделенных знаком |. Каждое значение состоит из описания и маски, также разделенных знаком |. Описание представляет собой обычный текст, поясняющий пользователю данную маску. Маска является шаблоном отображаемых файлов и состоит из имени и расширения. Если для одного описания приводится несколько масок, то они разделяются знаком ;.

Здесь фильтр формируется с двумя масками — маской для текстовых файлов и маской для всех файлов (под текстовыми понимаются файлы типов doc и txt).

Так как в раскрывающемся списке диалогового окна отображается только описание фильтра, то для удобства целесообразно включить в описание и маску, например, так:

Фильтр обычно формируется при проектировании приложения. Для этого из окна Инспектора объектов щелчком в области значения свойства Filter вызывается Редактор фильтра (Filter Editor).

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

Стандартные диалоговые окна выбора имени файла для открытия или сохранения файла вызываются на экран методом Execute. Эта функция в качестве результата возвращает логическое значение, позволяющее определить, как закрыт диалог. Если пользователь в процессе диалога нажал кнопку Open или Save, то диалог считается принятым, и функция Execute возвращает значение True. Если диалог был закрыт любым другим способом, то он считается не принятым, и функция возвращает значение False.

При нажатии кнопки Button2 появляется диалоговое окно OpenDialog1 выбора имени файла для открытия. При выборе имени текстового файла его содержимое загружается в компонент Memo1. Напомним, что многострочный редактор Memo позволяет работать с текстами в коде ANSI. При отмене диалога OpenDialog1 открытие файла не происходит.

Компоненты OpenPictureDialog и SavePictureDialog вызывают стандартные диалоги открытия и сохранения графических файлов. Эти стандартные диалоги отличаются от OpenDialog и SaveDialog видом окон (см. скриншот) и установленными значениями свойства Filter.

Так, по умолчанию свойство Filter установлено для отображения графических файлов следующих форматов:

  • JPEG (*.jpg);
  • JPEG (*.jpg);
  • растровое изображение (*.bmp);
  • значок (*.ico);

При использовании диалогов OpenPictureDialog и SavePictureDialog, а также OpenDialog и SaveDialog значение свойства Filter можно установить ранее рассмотренными способами, а также с помощью функции GraphicFilter (GraphicClass: TGraphicCiass) : String.

Параметр GraphicClass принадлежит к одному из графических классов: TBitmap, TGraphic (и его потомки), TIcon, TMetafile или TJPEGimage. Для работы с классом TJPEGimage нужно подключить модуль jpeg. В качестве результата функция GraphicFilter () возвращает строку с фильтрами для указанного графического класса:

TBitmap — Bitmaps (*.bmp) |*.bmp;

TIcon—Icons (* . ico) I * . ico;

TMetafile — All (*.emf;*.wmf) |*.emf;*.wmf|Enhanced Metafiles(*.emf)| *.emf|Metafiles(*.wmf) |*.wmf;

TJPEGimage — All (*.jpg;*.jpg) | *.jpg;*.jpg| JPEG Image File (*.jpg) |*.jpg| JPEG Image File (*.jpg)| *.jpg;

TGraphic — All (*.jpg;*.jpg;*.bmp;*.ico;*.emf;*.wmf) | *.jpg;*.jpg; *.bmp;*.ico;*.emf; *.wmf|JPEG Image File (*.jpg) | *.jpg| JPEG Image File (*.jpg) |*.jpgI Bitmaps (*.bmp) | *.bmp| Icons(*.ico) |*.ico | Enhanced Metafiles(*.emf)|*.emf|Metafiles(*.wmf)I*.wmf.

Если модуль jpeg в разделе uses не указан, то фильтры, соответствующие формату JPEG, будут отсутствовать.

Например, фильтр, заданный как OpenDialog1.Filter := GraphicFilter(TGraphic); позволяет отображать имена графических файлов допустимых форматов.


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

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

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

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

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

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

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

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

TSearchRec = record Time: Integer; // Время создания найденного файла

Size: Integer; // Размер найденного файла

Attr: Integer; // Атрибуты найденного файла

Name: TFileName; // Имя найденного файла

ExcludeAttr: Integer; // Исключаемые атрибуты найденного файла

FindHandle: THandle; // Указатель, необходимый для поиска

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

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

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

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

SearchRec:TSearchRec; begin // Ищем файл

if FindFirst(Editl.Text, faAnyFile,SearchRec)=0 then

Edit2.Text:=IntToStr(SearchRec. Size)+ 'байт';

//Закрываем поиск FindClose(SearchRec); end;

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

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

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

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

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

procedure ScanFolder(Folder: String);

procedure TForm1.ScanFolder(Folder: String); var

sr: TSearchRec; FileName:String;

if FindFirst(Folder+'\*.*', faAnyFile, sr) = 0 then begin repeat

if (sr.Name= 1 . 1) or (sr.Name=' . . ') then continue;

FileName := SlashSep(Folder, sr.Name);

if (sr.Attr and faDirectory) = faDirectory then begin

i f AnsiUpperCase(edLookFor;Text)=AnsiUpperCase(sr.Name) then Memol.Lines.Add(FileName) ;

FindClose(sr); end; end;

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

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

function SlashSep(Path, FName: string): string;

if Path[Length(Path)] <> '\' then Result := Path + '\'+ FName else Result := Path + FName;

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

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

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

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

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

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

Читайте также: