Справочник программиста на персональном компьютере фирмы IBM. Дисковые накопители
Страница 39. Чтение из файлов прямого доступа


     5.4.6 Чтение из файлов прямого доступа.


   Чтение  файлов прямого доступа является обратным процессом  по
отношению к их записи. MS DOS вычисляет позицию в файле на диске,
затем  считывает запись и помещает ее в память.  Затем  программа
должна разделить запись на поля в точности того же размера, кото-
рый был использован при конструировании записи.  Не забудьте уда-
лить символы пробела, добавленные при заподнении полей.  Обсужде-
ние записи данных в файлы прямого доступа [5.4.5] содержит инфор-
мацию, которая поможет Вам лучше понять информацию данного разде-
ла.

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


   Для  чтения  файла прямого доступа необходимо открыть  файл  и
определить поля записи, как  объяснено  в  разделе, относящемся к
записи в файлы прямого доступа.  Затем надо использовать оператор
GET# для чтения определенной записи с диска.  GET #1,23 считывает
запись  номер #23 из файла, открытого под номером #1.  При чтении
записи переменной, именованной  в  операторе FIELD, автоматически
присваивается соответствующее значение из записи.  Например, если
оператор FIELD имеет вид  FIELD  1,  20  AS X$, 2 AS Y$, то после
выполнения  оператора GET 1,23 переменной X$ будет присвоено зна-
чение первых 20-ти байтов записи 23,  а переменной Y$ - следующих
10-ти байтов.  Операторы,  аналогичные  RSET и LSET для выделения
полей данных отсутствуют.
   В  случае  числовых  полей, напоминаем, что  они  должны  быть
преобразованы в строковый  вид  с  помощью  функций  MKI$, MKS$ и
MKD$.   Для восстановления их оригинальных значений, с тем  чтобы
над ними можно было проводить операции и печатать их, надо преоб-
разовать  эти строки с помощью функций CVI, CVS и CVD.   Если  Y$
содержит целое число, то для  выполнения обратного преобразования
запишите  Y%  = CVI(Y$), при этом переменная Y%  будет  содержать
значение, которое  имела  переменная  перед тем как она была спе-
циально  обработана для записи в файл прямого доступа.   Если  Вы
выведете строковое значение переменной, то увидите, что это число
в интервале от 0 до 65535, закодированное в два символа ASCII.
   В  данном примере открывается файл, созданный в примере пункта
[5.4.5], и выводится содержимое любой из затребованных записей:

100 OPEN "A:NEWDATA" AS #1 LEN = 24    'открываем файл
110 FIELD 1, 18 AS LASTNAME$, 2 AS AGE$, 4 AS WEIGHT$
120 CLS: INPUT "What is the record number";R   'запрос записи
130 IF R*24 > LOF(1) THEN BEEP: PRINT"No such record": GOTO 120
140 GET #1,R                     'читаем запись из файла
150 PRINT LASTNAME$, CVI(AGE$), CVS(WEIGHT$)   'выводим ее
160 PRINT: PRINT "Do another (y/n)?"    'будем повторять?
170 C$ = INKEY$: IF C$ = "" THEN 170    'ожидаем ввода
180 IF C$ = "y" OR C$ = "Y" THEN 120    'повторяем, если надо
190 CLOSE                               'иначе закрываем файл

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


   Метод FCB доступа к файлам имеет  две функции для чтения запи-
сей с прямым доступом. С другой стороны, метод дескриптора файлов
использует ту же функцию, что и для  чтения последовательных фай-
лов. Два метода доступа рассматриваются отдельно.

Метод FCB:
   Функция 21H прерывания 21H читает одну запись из файла прямого
доступа.  Вторая функция, 27H, читает блок последовательных запи-
сей.   Создайте управляющий блок файла, как показано в [5.3.5]  и
откройте его [5.3.3].  После  того как FCB открыт, введите в него
значения полей размера записи (DW по смещению 14) и номера записи
прямого доступа (DD  по  смещению  33).   Если DS:DX указывают на

первый  байт FCB, то можно вызывать функцию 21H для чтения записи
и запись будет помещена в паямть, начиная с первого байта DTA.
   Если запись  успешно  прочитана,  то  в  AL будет возвращен 0.
Однако при этом нет гарантии, что чтение прошло без ошибок,  пос-
кольку неверный размер  записи  может  привести к тому, что части
прилегающих  записей  будут считаны, как будто это  одна  запись.
Если запрошена  запись  с  номером  большим,  чем число записей в
файле, то в AL будет возвращено 1 или 3.  Если был возвращен  код
3, то был считан самый конец  файла и была прочитана часть записи
данных. Если был возвращен код 1, то данные вообще не были счита-
ны.
   Данный пример считывает одну запись и помещает ее в DTA:

;---в сегменте данных
FCB         DB    1,'OLDDATA    ', 25 DUP (0)

;---открываем файл и устанавливаем поля FCB
   MOV  AH,0FH           ;номер функции
   LEA  DX,FCB           ;DS:DX указывают на FCB
   MOV  BX,DX            ;копируем смещение FCB
   INT  21H              ;открываем файл
   MOV  AX,55            ;размер записи 55 байтов
   MOV  [BX]+14,AX       ;помещаем в поле размера записи
   MOV  AX,22            ;номер записи для чтения
   MOV  [BX]+33,AX       ;помещаем в поле номера записи
   MOV  AX,0             ;обнуляем старшее слово этого поля
   MOV  [BX]+35,AX       ;
;---перенос данных из файла в DTA
   MOV  AH,21H           ;номер функции чтения с прямым доступом
   LEA  DX,FCB           ;DS:DX указывают на FCB
   INT  21H              ;читаем данные, помещая их в DTA
   CMP  AL,0             ;проверка на ошибку
   JNE  READ_ERROR       ;
;---позднее, закрываем файл
   MOV  AH,10            ;номер функции закрытия файла
   LEA  DX,FCB           ;DS:DX указывают на FCB
   INT  21H              ;закрываем файл

   Для  чтения  блока последовательных записей в память  за  один
прием надо использовать функцию 27H прерывания 21H. Ее выполнение
подготавливается  в точности так же, как и функции 21H, за исклю-
чением того, что вдобавок CX должен содержать число записей кото-
рые надо прочитать за один прием. При возврате CX будет содержать
число реально  прочитанных  записей.  Значения  возвращаемые в AL
совпадают с теми, которые возвращаеются функцией 21H.  В  отличии
от функции 21H поля FCB, в  которых хранится информация о положе-
нии записи (поле записи прямого доступа, текущего блока и текущей
записи) автоматически увеличиваются, с тем чтобы они указывали на
следующую несчитанную запись после выполнения функции.
   Отметим,  что как в случае чтения одной, так и в случае чтения
нескольких записей,  поля  текущего  блока  и  текущей записи FCB
устанавливаются по значению поля записи прямого доступа.  Если Вы

знаете значение текущего блока и  текущей записи, а не соответст-
вующий  номер записи прямого доступа, то используйте функцию  24H
прерывания 21H, чтобы она  проделала  вычисления  за Вас.  У этой
функции нет входных регистров, надо только, чтобы DS:DX указывали
на открытый FCB.  При возврате  поле записи прямого доступа будет
заполнено значением, соответствующим установке двух других полей.

Метод дескриптора файлов:
   В  предыдущем разделе показано, как писать записи прямого дос-
тупа с помощью  метода  дескриптора  файлов.  Процедура чтения из
файла  с прямым доступом подготавливается совершенно  аналогичным
образом, путем  вычисления  смещения  в  файле, на которое должен
указывать файловый указатель.  DS:DX должны указывать на буфер, в
который будет помещена запись,  после чего надо выполнить функцию
3FH прерывания 21H.  При входе CX должен содержать размер записи,
а BX - номер файла.

;---в сегменте данных
HANDLE       DB    ?
FILEPATH     DB    'A:OLDDATA',0
REC_BUFFER   DB    30 DUP(?)

;---открываем файл
   MOV  AH,3DH          ;номер функции
   MOV  AL,0            ;код открытия для чтения
   LEA  DX,FILEPATH     ;DS:DX указывают на путь к файлу
   INT  21H             ;открываем файл
   JC   OPEN_ERROR      ;проверка на ошибку
   MOV  HANDLE,AX       ;запоминаем номер файла
;---вычисляем позицию записи и устанавливаем файловый указатель
   MOV  AX,30           ;размер записи
   MOV  CX,54           ;читаем запись #54 (55-ю запись)
   MUL  CX              ;смещение записи в DX:AX
   MOV  CX,DX           ;помещаем старшее слово смещения в DX
   MOV  DX,AX           ;помещаем младшее слово смещения в CX
   MOV  AL,0            ;устанавливаем указатель на начало файла
   MOV  AH,42H          ;функция установки указателя
   MOV  BX,HANDLE       ;номер файла
   INT  21H             ;устанавливаем указатель
   JC   POINTER_ERROR   ;обработка ошибки
;---читаем запись с прямым доступом
   MOV  AH,3FH          ;номер функции
   MOV  BX,HANDLE       ;номер файла
   MOV  CX,30           ;размер записи
   LEA  DX,REC_BUFFER   ;DS:DX указывают на буфер для записи
   INT  21H             ;читаем запись
   JC   READ_ERROR      ;обработка ошибки

;---позднее, закрываем файл
   MOV  BX,HANDLE       ;номер файла
   MOV  AH,3EH          ;функция закрытия файла
   INT  21H             ;закрываем файл
   JC   CLOSE_ERROR     ;проверка на ошибку

 
« Предыдущая статья   Следующая статья »