FILES "A:MYFILE.DAT". Kак и в операционной системе имя файла
может содержать * и ?. Оператор FILES снабжает информацией поль-
зователя, но иногда наличие некоторого файла хочет проверить
программа. В этом случае надо открыть файл для последовательного
чтения и если он не существует, то возникнет ошибочная ситуация.
Смотрите обсуждение и пример в [5.2.3].
Для поиска любой информации, относящейся к корневому каталогу,
используйте процедуру на машинном языке, приведенную в [5.4.2].
После того как данные каталога в памяти, установите указатели,
как описано выше, и ведите поиск по буферу памяти с 32-байтным
интервалом. Hижеприведенный пример ищет элемент каталога, относя-
щийся к стертому файлу. Kогда файл стирается, то первый байт
имени файла заменяется на E5H, но все остальное содержимое данно-
го элемента остается неизменным. Kонечно, при этом освобождается
дисковое пространство, отведенное файлу в FAT. Процедура восста-
новления удаленного файла должна знать номер начального кластера
в FAT. В примере этот 2-байтный номер кластера помещается со
смещением 26 в элементе каталога.
100 '''чтение секторов каталога в память с сегмента &H2000
110 INPUT "Enter erased filename ", FNAME$
120 IF LEN(FNAME$) > 12 THEN BEEP: GOTO 110
130 IF INSTR(FNAME$,".") > 9 THEN BEEP: GOTO 110
140 '''дополнение имени и расширения файла нулями
150 Y = INSTR(FNAME$,".")
160 IF Y = 0 THEN FIRSTPART$ = FNAME$: GOTO 230
170 EXTEN$ = LEFT$(FNAME$, LEN(FNAME$) - Y)
180 EXTEN$ = EXTEN$ + STRING$(3 - LEN(EXTEN$),"")
190 FIRSTPART$ = RIGHT$(FNAME$,Y - 1)
200 FIRSTPART$ = FIRSTPART$ + STRING$(8 - LEN(FIRSTPART$),"")
210 FNAME$ = FIRSTPART$ + EXTEN$
220 '''теперь хотим найти удаленный файл
230 MID$(FNAME$,1,1) = CHR$(&HE5) 'заменяем первый символ
240 DIRPTR = 0 'указатель на элемент
250 FIELDPTR = 26 'указатель на номер кластера
260 FOR N = 1 TO 112 'на дискете 112 элементов
270 X$ = "" 'чистим X$
280 FOR M = 0 TO 10 'читаем имя файла из каталога
290 X$ = X$ + PEEK(DIRPTR + M) 'берем по символу
300 NEXT '
310 IF X$ = FNAME$ THEN 340 'совпадает с введенной строкой
320 NEXT 'если нет, то следующий
330 PRINT "Too late - file entry obliterated": END 'уже нет
340 X = PEEK(DIRPTR + FIELDPTR) 'нашли его, берем 1-й байт и
350 Y = PEEK(DIRPTR + FIELDPTR + 1) '2-й байт номера кластера
360 Z = X + 256*Y 'теперь номер кластера в Z
Средний уровень.
MS DOS обеспечивает две пары функций для поиска файлов, одна
для файлов, открытых методом управляющих блоков файла, а другая -
для файлов, открытых методом дескриптора файлов. Одна из функций
каждой пары ищет первое появление имени файла в каталоге, а дру-
гая ищет последующие появления, когда в имени файла содержатся
джокеры. Только метод, использующий дескриптор файла позволяет
искать подкаталоги.
Метод FCB:
Функция 11H прерывания 21H ищет первое появление файла. Уста-
новите DS:DX на неоткрытый FCB и выполните функцию. При возврате
AL будет содержать 0, если файл найден, и FF - если нет. DTA
заполняется информацией из каталога. Для обычных FCB первый байт
DTA содержит номер накопителя (1 = A и т.д.), а следующие 32
байта содержат элемент каталога. Для расширенного FCB первые 7
байтов файла копируются в первые 7 байтов расширенного FCB, вось-
мой байт указывает на накопитель, а следующие 32 байта - элемент
каталога.
;---в сегменте данных
FCB DB 1,'NEWDATABAK',25DUP(0)
;---ищем файл
MOV AH,11H ;функция поиска в каталоге
LEA DX,FCB ;указываем на FCB
INT 21H ;ищем
CMP AL,0 ;успешно?
JNE NO_FILE ;если нет, то процедура обработки ошибки
LEA BX,DTA ;теперь DS:BX указывает на элемент каталога
После использования функции 11H можно использовать функцию 12H
для поиска следующих подходящих элементов, когда имя файла содер-
жит джокеры. В данном случае в имени файла допустим только символ
"?", но не "*". Эта функция работает в точности так же, как и
первая, и если найден второй файл, то информация о первом файле в
DTA будет уничтожена повторной записью.
Метод дескриптора файлов:
Функция 4EH прерывания 21H ищет файл с данным именем. DS:DX
должны указывать на строку, дающую путь файла. Hапример, B:\EURO-
PE\FRANCE\PARIS указывает на файл PARIS. Строка может содержать
до 63 символов и завершаться символом ASCII 0. Имя файла может
содержать джокеры, включая как "?", так и "*". Поместите атрибут
файла в CX; если он обычный то 0, в противном случае проконсуль-
тируйтесь в [5.2.6] относительно значений атрибута.
При возврает устанавливается флаг переноса, если файл не най-
ден. Если файл найден, то функция заполняет DTA информацией о
файле. Отметим частный случай использования DTA методом дескрип-
тора файлов - обычно, DTA используется функциями MS DOS для рабо-
ты через FCB. Первые 21 байт DTA зарезервированы DOS для поиска
следующих совпадающих файлов. Двадцать второй байт дает атрибут
файла, за ним следуют два байта, содержащие время и еще два байта
содержащие дату. Следующие 4 байта содержат размер файла (младшее
слово сначала). И, наконец, дается имя файла в виде строки пере-
менной длины, заканчивающейся байтом ASCII 0. Точка (ASCII 46)
разделяет имя и расширение и не один из этих элементов не запол-
нен пробелами.
;---в сегменте данных
PATH DB 'B:FRANCE\PARIS\4EME',0
;---ищем файл
MOV AH,4EH ;номер функции
LEA DX,PATH ;DS:DX указывают на путь
MOV CX,0 ;обычный атрибут файла
INT 21H ;ищем файл
JC NO_FILE ;уход, если не найден
LEA BX,DTA ;DS:BX указывают на DTA
MOV AL,[BX]+21 ;теперь атрибут файла в AL
Следующее появление имени файла (когда используются джокеры)
ищется с помощью функции 4FH прерывания 21H. Она готовится в
точности так же, как и функция 4EH, при этом указатель DTA не
должен меняться. Kогда других совпадений не найдено, то устанав-
ливается флаг переноса, а в AX появляется 18.
5.2.2 Создание/удаление подкаталога.
Программа может создавать или удалять подкаталоги, при выпол-
нении некоторых условий. Для создания подкаталога необходимо,
чтобы было по крайней мере одно пустое место в корневом каталоге.
Для удаления подкаталога необходимо, чтобы он не содержал файлов
или ссылок на другие подкаталоги. Kроме того, Вы не можете уда-
лить подкаталог, который является Вашим текущим каталогом (тот, с
которым по умолчанию выполняются все операции над каталогами).
Отметим также, что невозможно удалить корневой каталог.
Высокий уровень.
Бейсик предоставляет команды MKDIR (создай каталог) и RMDIR
(удали каталог). За обеими должны следовать стандартные пути
указания каталога, содержащие до 63 символов, включая имя накопи-
теля. Путь должен быть заключен в кавычки. Чтобы добавить подка-
талог с именем STORKS в подкаталог BIRDS напишите MKDIR "B:MAM-
MALS\BIRDS\STORKS". После выполнения этой команды будет создан
файл STORKS, используемый как подкаталог и факт его существования
будет отражен в создании элемента с именем STORKS в подкаталоге с
именем BIRDS. Для удаления этого подкаталога надо сначала удалить
из него все файлы [5.3.2]. Затем надо использовать команду RMDIR
"B:MAMMALS\BIRDS\STORKS".
В этих примерах предполагалось, что Вашим текущим каталогом
являлся корневой каталог. Однако, если Ваш текущий каталог нахо-
дится где-то на пути к подкаталогу, над которым осуществляются
операции, то нет необходимости указывать весь путь. Поэтому, если
Вашим текущим каталогом является BIRDS, то для создания или уда-
ления подкаталога STORKS можно использовать команды MKDIR
"\STORKS" или RMDIR "\STORKS".
Средний уровень.
Поскольку управляющие блоки файлов обслуживают только корневой
каталог, то для создания или удаления подкаталога надо использо-
вать дескрипторы файлов.
Создание подкаталога:
DS:DX должны указывать на строку, дающую накопитель и путь к
каталогу, в котором должен быть создан подкаталог. Строка должна
завершаться байтом ASCII 0. Для открытия подкаталога с именем
PRIMATES в корневом каталоге накопителя A: надо записать строку в
виде "A:\PRIMATES". Для открытия подкаталога в другом подкаталоге
с именем MAMMALS напишите "A:\MAMMALS\PRIMATES". Имя накопителя
A: может быть опущено если Вы работаете с накопителем, используе-
мым по умолчанию, и путь может начинаться с текущего каталога.
Поместите в AH 39H и выполните прерывание 21H; если указан пра-
вильный путь, то будет создан новый каталог. В противном случае
будет установлен флаг переноса, а AX будет содержать код ошибки 3
(путь неверен) или 5 (нет доступа). В примере создается подката-
лог PRIMATES:
;---в сегменте данных
PATH DB 'A:MAMMALS\PRIMATES',0
;---создаем подкаталог с именем PRIMATES
LEA DX,PATH ;DS:DX должны указывать на путь
MOV AH,39H ;номер функции
INT 21H ;создаем подкаталог
JC ERROR_ROUT ;обработка ошибок
Удаление подкаталога:
Для удаления подкаталога надо сформировать строку, в точностью
совпадающую с той, которую Вы указывали при создании каталога.
Затем поместите в AH 3AH и выполните прерывание 21H. Опять при
невыполнении функции в AX будут возвращены коды 3 или 5 (код 5
может указывать, что каталог непустой).
5.2.3 Чтение/изменение подкаталога.
Подкаталоги во многом подобны корневому каталогу, за исключе-
нием того, что они хранятся как обычные файлы, а не в заранее
предопределенных секторах. Подкаталоги невозможно спутать с обыч-
ными файлами, поскольку объект каталога, относящийся к подкатало-
гу, имеет специальный байт атрибутов (с установленным битом 5 -
см. [5.2.6]). Подкаталоги начинаются с двух специальных 32-байт-
ных объектов, первый из которых имеет имя точка, а второй - две
точки. Они ориентируют подкаталог среди окружающих каталогов.
Ссылки на подкаталоги нижнего уровня записываются как обычные
ссылки на файлы.
Предполагается, что подкаталог может быть прочитан как любой
другой файл, поэтому вроде бы не составляет труда загрузить его в
память. Hо, к сожалению, создатели MS DOS поместили 0 в поле
длины файла для элементов, относящихся к подкаталогам. В резуль-
тате DOS считает, что этот файл имеет нулевую длину и отказывает-
ся читать его. Hет простого способа преодолеть эту проблему.
Высокий уровень.
В Бейсике команда FILES может использовать стандартные имена
путей для вывода подкаталога; например, FILES "B:MAMMALS\BIRDS"
выводит все файлы, содержащиеся в подкаталоге BIRDS. Эта команда
может быть использована и для получения информации о наличии в
каталоге определенного файла. Hапример, FILES "LEVEL1\NEWDATA"
ищет файл NEWDATA и выводит его имя, если он найден. Хотя это
может быть полезным для пользователя, но часто самой программе
необходимо знать существует или нет указанный файл. Чтобы устано-
вить это попытайтесь открыть файл для последовательного чтения.
Если он не будет найден, то возникнет ошибочное условие 63. Соз-
дайте процедуру обработки ошибок, как описано в [5.4.8]. Затем
используйте переменную, чтобы отметить был ли найден требуемый
файл (в нашем примере переменная "EXISTS"). Если программе не
нужно, что этот файл был открыт, то закройте его перед тем как
двинуться дальше.
100 ON ERROR GOTO 1000 'процедура обработки ошибок
110 EXISTS = 1 'начальное значение "флага"
120 INPUT "Enter filename: ",S$ 'запрос имени файла
130 OPEN S$ FOR INPUT AS #3 'открываем его для послед. чтения
140 IF EXISTS = 0 THEN BEEP: PRINT "File does not exist"