Справочник программиста на персональном компьютере фирмы IBM. Дисковые накопители - Чтение/изменение подкаталога

ОГЛАВЛЕНИЕ

     5.2.3 Чтение/изменение подкаталога.


   Подкаталоги во многом подобны корневому  каталогу, за исключе-
нием  того,  что они хранятся как обычные файлы, а  не в  заранее
предопределенных секторах. Подкаталоги невозможно спутать с обыч-
ными файлами, поскольку объект каталога, относящийся к подкатало-
гу, имеет специальный байт  атрибутов  (с установленным битом 5 -
см.  [5.2.6]). Подкаталоги начинаются с двух специальных 32-байт-
ных объектов, первый из которых  имеет  имя точка, а второй - две
точки.   Они ориентируют подкаталог среди  окружающих  каталогов.
Ссылки на подкаталоги  нижнего  уровня  записываются  как обычные
ссылки на файлы.
   Предполагается,  что подкаталог может быть прочитан как  любой
другой файл, поэтому вроде бы не составляет труда загрузить его в
память.   Но,  к сожалению, создатели MS DOS поместили  0 в  поле
длины файла для элементов, относящихся к подкаталогам.  В резуль-
тате DOS считает, что этот файл имеет нулевую длину и отказывает-
ся читать его. Нет простого способа преодолеть эту проблему.

   Высокий уровень.


   В Бейсике команда FILES может  использовать  стандартные имена
путей  для вывода подкаталога; например, FILES  "B:MAMMALS\BIRDS"

выводит все файлы, содержащиеся в подкаталоге BIRDS.  Эта команда
может  быть использована и для получения информации о  наличии  в
каталоге определенного  файла.  Например,  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"
 .
 .
1000 IF ERR = 53 THEN 1500  'файл не существует?
1010 IF ERR = 64 THEN ...   'другие ошибки
 .
1500 EXISTS = 0             'меняем значение флага
1510 RESUME 140             'продолжаем выполнение программы

   Средний уровень.


   Функции работы через  дескрипторы  файлов, которые использова-
лись для доступа к корневому каталогу [5.2.1] могут так же просто
обращаться к любому  подкаталогу.   Чтобы  вывести все содержимое
каталога  надо просто использовать функцию 4EH для поиска  файлов
*.*, а затем повторять поиск, используя функцию 4FH. Когда больше
не  будет файлов, то будет установлен флаг переноса, а  AL  будет

содержать  18.  Каждый раз, когда будет обнаружен очередной  эле-
мент, в DTA будет записана информация о файле, включая полный его
путь  (отмечаем использование DTA в функциях, использующих  деск-
риптор файла).  Следующий пример выводит полные пути всех обычных
файлов подкаталога.

;---в сегменте данных
PATH     DB   'A:MAMMALS\*.*',0
DTAH     DB   256 DUP(?)

;---установка DTA
            LEA  DX,DTA        ;DS:DX указывают на DTA
            MOV  AH,1AH        ;функция установки DTA
            INT  21H           ;устанавливаем DTA

;---ищем первый файл
            MOV  AH,4EH        ;номер функции
            LEA  DX,PATH       ;указываем на строку пути
            MOV  CX,0          ;только нормальные атрибуты
            INT  21H           ;ищем *.*
            JC   ERROR         ;обработка ошибок
;---выводим имя файла
NEXT_LINE:  LEA  BX,DTA        ;BX указывает на DTA
            ADD  BX,30         ;смещение для имени файла
NEXT_CHAR:  MOV  DL,[BX]       ;получаем символ из имени
            CMP  DL,0          ;проверка на конец строки
            JE   END_STR       ;уход, если конец
            MOV  AH,2          ;иначе, выодим символ
            INT  21H           ;
            INC  BX            ;увеличиваем указатель
            JMP  SHORT NEXT_CHAR  ;следующий символ
;---возврат каретки/перевод строки в конце строки
END_STR:    MOV  AH,2          ;функция вывода символа
            MOV  DL,13         ;код возврата каретки
            INT  21H           ;выводим
            MOV  DL,10         ;код перевода строки
            INT  21H           ;выводим
;---ищем следующий файл
            LEA  DX,PATH       ;указываем на строку пути
            MOV  AH,4FH        ;номер функции
            INT  21H           ;ищем следующий файл
            JC   FINISHED      ;если нет, то выход
            JMP  SHORT NEXT_LINE  ;иначе выводим имя файла
FINISHED: