Работа с атрибутами файлов проводится при помощи двух процедур:
GetFAttr (VAR f; VAR Attr: Word);
и
SetFAttr (VAR f; Attr: Word).
Они дают более простой доступ к атрибутам файла, чем рассмотренные выше способы анализа файловых типов, и позволяют переустанавливать его без опасения за корректность проводимых {365} действий. Но применение процедур требует одного условия, а именно: обобщенная файловая переменная должна быть предварительно связана с каким-либо физическим файлом на диске, но этот файл должен быть закрыт. Короче говоря, процедуры GetFAttr и SetFAttr могут появляться в программе только в связках (рис. 16.10).
USES DOS; VAR f: File Of Real; t: Text; FA: Word; BEGIN Assign(f, 'DIFFUR.DAT'); GetFAttr(f, FA); if (FA and ReadOnly) = ReadOnly then SetFAttr(f, FA-ReadOnly); Rewrite(f); ... Close(f); FA:= Archive + ReadOnly + Hidden; Assign(t, 'TEXT.FIL'); SetFAttr(t, FA); ... END. |
Рис. 16.10
В примере на рис. 16.10 анализируется атрибут файла DIFFUR.DAT, и если он содержит в себе защиту от записи, то она снимается и можно открывать файл. Второй файл TEXT.FIL снабжается целым «букетом» атрибутов защиты.
Используя константы атрибутов, легко анализировать и изменять атрибуты файлов. Пусть FA — считанный только что атрибут файла. Тогда выражение типа
(FA and Hidden) = Hidden
анализирует наличие атрибута Hidden. Если оно истинно, то атрибут имеется. Выражение типа
FA:= FA or ReadOnly
подготовит FA для установки, включив режим «только для чтения»;
FA:= FA and (AnyFile - ReadOnly)
сделает все наоборот: исключит ReadOnly из суммы атрибутов, а оператор
FA:= FA xor SysFile
сменит атрибут системности на обратный. {366}
Использовать атрибуты нужно аккуратно, ибо установив, например, атрибут ReadOnly файлу f, мы тем самым закроем возможность открывать этот файл для записи (будет ошибка), и надо будет отключать действие этого атрибута.
Естественно, следует помнить и об эффектах иных атрибутов. Так, поставив какому-либо каталогу атрибут Hidden, не следует потом удивляться, куда он делся при подаче команды DIR, как не стоит удивляться тому, что файлы с нарушенным атрибутом архивности не копируются командой BACKUP.
Анализ имен файлов
16.4.5.1. Процедура FSplit(X: PathStr, VAR Dir: DirStr, VAR Name: NameStr, VAR Ext: ExtStr). Эта процедура служит для разбиения на части полного имени файла. Под полным именем мы понимаем конструкцию из маршрута на диске и собственно имени файла. Принимая на входе строку X, процедура разбивает ее на три подстроки соответствующих типов:
Dir — имя маршрута на диске;
Name — имя файла (до восьми символов без точки);
Ext — точка и следующее за ней расширение.
Если при разборе строки X окажется невозможным выделить какой-либо ее компонент, то вернется значение '' (пустая строка). Примеры вызовов и их результаты можно увидеть в табл. 16.4.
Таблица 16.4
Значение X | Dir= | Name= | Ext= |
‘C:\DOS33\SYS.COM’ | ‘C:\DOS33\’ | ‘SYS’ | ‘.COM’ |
‘BILL.EXE’ | ‘’ | ‘BILL’ | ‘.EXE’ |
‘GAMES\DIGGER’ | ‘GAMES\’ | ‘DIGGER’ | ‘’ |
‘GAMES\DIGGER\’ | ‘GAMES\DIGGER\’ | ‘’ | ‘’ |
‘A:FILE.COM’ | ‘A:’ | ‘FILE’ | ‘.COM’ |
В некоторых случаях возможна неоднозначная трактовка параметра X. Так, в примере с 'GAMES\DIGGER' подстрока 'DIGGER' может быть и именем файла, и именем подкаталога.
Процедура FSplit никогда не запрашивает диск, чтобы разобраться в подобных проблемах. Она просто считает последнее слово после символа '\' в строке именем файла. Если подразумевается, что DIGGER — имя подкаталога, то надо дописывать символ разделения каталогов. {367}
16.4.5.2. Функция FExpand(X: PathStr): PathStr. Действие функции состоит в приведении строки X к полному имени файла, причем к какому именно, зависит от значения X.
Если X — просто имя файла или имя файла с указанием его подкаталога относительно текущего местонахождения, то функция допишет к X полный маршрут текущего положения. Но если X уже содержит полное имя, то оно просто перепишется заглавными буквами без добавления маршрута. Сказанное выше иллюстрируется табл. 16.5 (считается, что текущий каталог — C:\TEST):
Таблица 16.5
Пример вызова | Возвращаемое значение |
...:=Fexpand(‘test.txt’) | ‘C:\TEST\TEST.TXT’ |
...:=Fexpand(‘..\DEMO\d.pas’) | ‘C:\DEMO\D.PAS’ |
...:=Fexpand(‘..\auto.bat ’) | ‘C:\AUTO.BAT’ |
...:=Fexpand(‘\LEX\out.txt ’) | ‘C:\LEX\OUR.TXT’ |
...:=Fexpand(‘\’) | ‘C:\’ |
...:=Fexpand(‘\\’) | ‘C:\\ |
...:=Fexpand(‘SUBDIR\’) | ‘C:\TEST\SUBDIR\’ |
...:=Fexpand(‘A:\LEX\our.txt’) |
Программа на рис. 16.11 показывает, как можно применить процедуру FSplit и функцию FExpand для написания заведомо «капризных» программ, которые работают только с файлами из текущего каталога.
USES DOS; { ПРИМЕР ОБРАБОТКИ ИМЕН ФАЙЛОВ } VAR X, FullName: PathStr; Dir: DirStr; Name: NameStr; Ext: ExtStr; BEGIN Write('Введите полное имя обрабатываемого файла: '); ReadLn(X); FSplit(X, Dir, Name, Ext); { состав введенного имени } X:=FExpand(X); { перевод в верхний регистр } if (Dir=' ') or {He введен путь или же ка- } (X<>FExpand(Name+Ext)) { талог при X - не текущий. } then begin { Файл не оттуда! Конец. } WriteLn(#10'Ошибка в имени'+ или попытка обмануть программу!'); Halt end; { if } ... { работа с верным именем } END. |
Рис. 16.11 {368}
Не следует забывать, что параметры и переменные, стоящие в вызовах этих процедур, должны быть описаны соответствующими типами, хотя после вызовов с ними можно обращаться, как с обычными строками назначенной длины.