КОМПЬЮТЕРНЫЕ КУРСЫ "ПОИСК"
[Главная страница] [Delphi] [Контакты]
При поиске файлов с помощью Delphi используется запись TSearchRec и следующие три функции: FindFirst, FindNext и FindClose. Запись TSearchRec и три функции объявлены в модуле SysUtils.
Чтобы начать поиск каталога, вы должны вызвать функцию FindFirst:
function FindFirst(const Path: string; Attr: Integer; var F: TSearchRec): Integer;
При вызове функции FindFirst для начала поиска файлов вы должны передать в параметре Path как путь к каталогу, так и маску файлов. Следовательно, если необходимо найти все текстовые файлы в корневом каталоге диска С. укажите С:\*.txt в параметре Path.
Параметр Attr позволяет искать дополнительные типы файлов — системные файлы, скрытые файлы и тому подобные. В качестве параметра Attr могут быть переданы следующие константы, которые также объявлены в модуле SysUtils: faReadOnly, faHidden, faSysFile, faDirectory, faArchive и faAnyFile. Существует также константа faVolumelD, но она нигде не является важной и обозначена как неиспользуемая.
При вызове функций FindFirst и FindNext в качестве параметра F необходимо передавать переменную TSearchRec. Обе функции хранят результаты поиска в параметре F, и обе возвращают 0, если файл был найден, или флаг ошибки, не равный 0, если подходящих файлов найдено не было.
Если функция FindFirst возвращает 0, вы можете вызвать функцию FindNext в цикле, чтобы попробовать найти другие файлы, совпадающие с критерием поиска.
В конце следует вызвать функцию FindClose, чтобы освободить память, занимаемую функцией FindFirst:
procedure FindClose (var F: TSearchRec);
В листинге ниже показано, как производится поиск всех файлов в корневом каталоге диска С.
type TForm1 = class(TForm) ListBox1: TListBox; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure ReadDirectory(const APath: string; AList: TStrings); var sRec: TSearchRec; begin AList.Clear; AList.BeginUpdate; if FindFirst(APath, faAnyFile, sRec) = 0 then try repeat AList.Add(sRec.Name); until FindNext(sRec) <> 0; // Повторять до флага ошибки finally FindClose(sRec); end; // завершение конструкции FindFirst AList.EndUpdate; end; procedure TForm1.FormCreate(Sender: TObject); begin ReadDirectory('c:\*.*', ListBox1.Items); end;
Перечисление доступных устройств
Перечислить доступные устройства можно с помощью API-функции
GetLogicalDrives или API-функции
GetDriveType (обе функции объявлены в модуле
Windows).
Функция GetLogicalDrives является очень
простой, поскольку она не принимает никаких параметров;
function GetLogicalDrives: DWORD; stdcall;
Эта функция имеет серьезный недостаток: необходимо знать о том, как проверить, что определенный бит в результирующем значении включен или выключен. Она возвращает битовую маску, в которой бит в позиции 0 представляет устройство А, бит в позиции 1 — устройство В и так далее.
Процедура EnumerateDrives демонстрирует использование функции GetLogicalDrives для перечисления доступных устройств.
procedure EnumerateDrives(AList: TStrings); var Cnd: Integer; Disks: set of 0..25; Cnt: Integer; begin AList.Clear; Integer(Disks) := GetLogicalDrives; { Цикл по результату Integer и проверка каждого бита } for Cnt := 0 to 25 do if Cnt in Disks then AList.Add(Chr(Cnt + 65) + ':\'); end;
Код для перечисления доступных устройств будет более понятен, если использовать функцию GetDriveType. Функция GetDriveType служит для определения, является ли устройство фиксированным, съемным или другим, однако ее можно использовать и для перечисления устройств.
Функция GetDriveType принимает указатель на строку с завершающим нулем, содержащую корневой каталог диска, который требуется проверить. Строка, содержащая корневой каталог, должна включать символ обратной косой черты, например, х:\.
function GetDriveType(lpRootPathName: PChar): UINT; stdcall;
В случае успешного выполнения эта функция возвращает одну из констант, перечисленных ниже.
Константа | Описание |
---|---|
DRIVE_UNKNOWN | Неизвестный тип устройства. |
DRIVE_NO_ROOT_DIR | Корневой каталог не существует. |
DRIVE_REMOVAELE | Устройство является съемным. |
DRIVE_FIXED | Устройство является фиксированным. |
DRIVE_REMOTE | Устройство является сетевым диском. |
DRIVE_CDROM | Устройство является приводом CD-ROM. |
DRIVE_RAMDISK | Устройство является виртуальным диском (RAM-диском). |
Процедура EnumerateDrives2 в листинге ниже демонстрирует использование функции GetDriveType для перечисления доступных устройств.
procedure EnumrateDrives2(AList: TStrings); var c: Char; begin AList.Clear; for c in ['A'..'Z'] do if GetDriveType(PChar(c + ':\')) <> DRIVE_NO_ROOT_DIR then AList.Add(c + ':\'); end;
В заключение, можно создать простой обозреватель каталогов, добавив в окно Designer Surface (Окно конструктора) компонент TComboBox, и добавив в него доступные устройства в событии OnCreate формы.
Вам придется также присвоить свойству Style компонента TComboBox значение csDropDownList, чтобы пользователь мог выбирать только существующие элементы, и написать обработчик события для его события OnChange, чтобы просматривать корневой каталог выбранного диска:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TMainForm = class(TForm) ListBox1: TListBox; ComboBox1: TComboBox; procedure FormCreate(Sender: TObject); procedure ComboBox1Change(Sender: TObject); private { Private declarations } public { Public declarations } end; var MainForm: TMainForm; implementation {$R *.dfm} procedure ReadDirectory(const APath: string; AList: TStrings); var sRec: TSearchRec; begin AList.Clear; AList.BeginUpdate; if FindFirst(APath, faAnyFile, sRec) = 0 then try repeat AList.Add(sRec.Name); until FindNext(sRec) <> 0; // Повторять до флага ошибки finally FindClose(sRec); end; // завершение конструкции FindFirst AList.EndUpdate; end; procedure EnumrateDrives(AList: TStrings); var Cnd: Integer; Disks: set of 0..25; Cnt: Integer; begin AList.Clear; Integer(Disks) := GetLogicalDrives; { Цикл по результату Integer и проверка каждого бита } for Cnt := 0 to 25 do if Cnt in Disks then AList.Add(Chr(Cnt + 65) + ':\'); end; procedure EnumrateDrives2(AList: TStrings); var c: Char; begin AList.Clear; for c in ['A'..'Z'] do if GetDriveType(PChar(c + ':\')) <> DRIVE_NO_ROOT_DIR then AList.Add(c + ':\'); end; procedure TMainForm.ComboBox1Change(Sender: TObject); begin ReadDirectory(ComboBox1.Text + '*.*', ListBox1.Items); end; procedure TMainForm.FormCreate(Sender: TObject); begin with ComboBox1 do begin EnumrateDrives2(Items); ItemIndex := Items.IndexOf('C:\'); end; ReadDirectory('c:\*.*', ListBox1.Items); end; end.
Источник: Иван Хладни - Внутренний мир Borland Delphi 2006.