16.4.3.1. Процедуры FindFirst(Path: String; Attrib: Word; VAR SR: SearchRec) и FindNextt(VAR SR: SearchRec). Эти процедуры предназначены для нахождения файлов на диске и всегда сопряжены между собой. Процедура FindFirst принимает в виде параметров строку с указанием маршрута поиска и имени файла (или шаблона для имен файлов) и числовое значение Attrib, указывающее атрибут искомых файлов. Атрибут может задаваться константами или их суммами. Он показывает, какие именно типы имен надо найти. Вызов процедуры FindFirst при заданных значениях параметров Path и Attrib должен производиться один раз. При этом в переменную SR предопределенного типа SearchRec запишутся параметры первого найденного файла (имя, атрибут, дата и время создания и его длина). Кроме этого, будет подготовлена специальная системная запись в памяти для ее дальнейшего использования процедурой FindNext. Эта процедура всегда должна вызываться после FindFirst (или не вызываться вовсе в противном случае). FindNext просто записывает в переданную ей переменную SR параметры следующего найденного файла, удовлетворяющего значениям Path и Attrib.
Контролером работы обеих процедур является переменная DosError. Она равна нулю, если вызов процедур дал какие-либо реальные результаты. Если же вызов закончился ошибкой (такое будет, если неверно задать запрос, или не существует искомых
USES DOS; { ПРИМЕР ПОИСКА МЕТКИ ДИСКА } { Функция возвращает метку диска. } FUNCTION GetVolume(Disk: String): String; VAR SR: SearchRec; BEGIN { Поиск. Имя диска дописывается до шаблона.} FindFirst(Disk+'\*.*', VolumeID, SR); case DosError of { анализ: } 0: GetVolume = SR.Name; { нашлась } 18: GetVolume = 'NO LABEL' { не нашлась } else GetVolume = 'ERROR'#7 { ошибка } end {case} END; BEGIN { ПРИМЕР ВЫЗОВА } WriteLn('Метка диска С: ', GetVolume('С:')); ReadLn { пауза до нажатия клавиши ввода } END. |
Рис. 16.7 {362}
файлов, или их список исчерпался при очередном запросе FindNext), DosError будет хранить ее код. При этом FindFirst может дать коды 2 и 18, a FindNext — только 18.
Ряд примеров (рис. 16.7,16.8,16.9) показывает, как можно использовать описанные процедуры.
USES DOS; { ПРИМЕР ПРОВЕРКИ СУЩЕСТВОВАНИЯ ФАЙЛА } (Функция возвращает True, если файл FileName существует. } FUNCTION FileExists(FileName: String): Boolean; VAR SR: SearchRec; BEGIN { Поиск происходит только среди файлов. } FindFirst(FileName,AnyFile-VolumeID-Directory,SR); FileExists:= (DosError = 0) END; BEGIN { — ПРИМЕР ВЫЗОВА — } if FileExists('C:\PASCAL\*.PAS') then begin WriteLn('Здесь есть Паскаль-программы!’); if FileExists('C:\PASCAL\demo.pas ‘) then WriteLn('...И файл DEMO тоже здесь есть!') else WriteLn('Но среди них нет файла DEMO...'); end {then} else WriteLn(В каталоге нечего искать!); ReadLn { пауза до нажатия клавиши ввода } END. |
Рис. 16.8
USES DOS; { ПРИМЕР ПОКАЗА СОДЕРЖИМОГО КАТАЛОГА } { ПРОЦЕДУРА ПОКАЗЫВАЕТ СПИСОК СОДЕРЖИМОГО ДИСКА ПО } { ШАБЛОНУ Where } PROCEDURE ShowDisk(Where: PathStr); TYPE { виды атрибутов } AttrType = (RO, Hid, Sys, Vol, Dir, Arc); CONST { их обозначения } AttrText: Array[AttrType] of.Char = ('R', 'H', 'S', ‘V’, 'D', 'A'); { их значения } AttrVal: Array [AttrType] of Byte = (1, 2, 4, 8, 16, 32); |
Рис. 16.9 {363}
VAR i: AttrType; { переменная цикла по атрибутам } SR: SearchRec; DT: DateTime; BEGIN if Where=' ' { Если пустая строка, } then Where:='*.*'; { то дописать шаблон. } { Поиск происходит среди файлов и каталогов:} FindFirst(Where, AnyFile, SR); { найти первый файл } while DosError = 0 do begin { пока нет ошибки } with SR do begin { очередной объект } Write(Name:15, Size:10); UnPackTime(Time, DT); with DT do Write(Day:5,'-',Month:2, '-',Year:4, Hour:5, ':', Min:2, ':', Sec:2,' '); for i:=RO to Arc do { Цикл по атрибутам } if (Attr and AttrVal[i]) = AttrVal[i] then Write(AttrText[i]) else Write('.'); WriteLn end; {with SR} FindNext(SR) { поиск следующего } end {while} END; { ПРИМЕР ВЫЗОВА } BEGIN ShowDisk('C:\*.*'); ReadLn { пауза до нажатия клавиши ввода } END. |
Рис. 16.9 (окончание)
Функция GetVolume возвращает метку диска, которая была установлена при форматировании или командой MS-DOS LABEL. Метка диска одна, поэтому используется только вызов FindFirst. С помощью FindFirst можно проверять наличие файла в определенном месте.
Последний пример показывает, как написать процедуру показа содержимого каталога (как это делается, например, в системах PC TOOLS или Norton Commander).
16.4.3.2. Функция FSearch(Path: PathStr, DirList: String): PathStr. Эта функция возвращает строку типа PathStr, в которой содержится имя и адрес файла на диске. Параметры функции несколько необычны. Первый параметр Path задает имя файла, который нужно отыскать, а второй параметр DirList является списком маршрутов, разделенных точкой с запятой и указывающих, где {364} именно искать файл. Возможные вызовы функции FSearch могут иметь такой вид:
USES DOS;
VAR S: PathStr;
BEGIN
{Поиск файла в списке каталогов: }
S:=FSearch('MYFILE.DOC', 'C:\;C:\TOOLS;C:\HELP;D:\');
...
{Поиск файла в одном каталоге: }
S:= FSearch('YOURFILE.PAS', 'C:\PASCAL\PAS');
...
{ Поиск файла в текущем каталоге: }
S:= FSearch('OURFILE.PAS', ‘ ‘);
...
END.
Перед тем как начать поиск файла в каталогах списка DirList, функция всегда попытается отыскать его в текущем каталоге. Если файл будет найден, то в переменную S запишется имя файла из параметра Path, в противном случае функция вернет пустую строку. Легко заметить, что параметр DirList аналогичен по синтаксису команде РАТН=... MS-DOS. Поэтому, если программе надо искать файл (не обязательно.СОМ или.ЕХЕ) в общедоступных каталогах, то можно построить вызов
S: = FSearch('MyFile.txt', GetEnv('PATH'));
Функцию FSearch можно, в принципе, использовать для проверки наличия файла в указанном месте. Более того, именно так и надо поступать, если поиск ведется во многих местах. Но для нахождения файла в одном конкретном месте более эффективна процедура, построенная из FindFirst и FindNext.