Глава 5. Дисковые накопители.
Раздел 4. Чтение и запись файла.
5.4.6 Чтение из файлов прямого доступа.
Чтение файлов прямого доступа является обратным процессом по отношению к их записи. MS DOS вычисляет позицию в файле на диске, затем считывает запись и помещает ее в память. Затем программа должна разделить запись на поля в точности того же размера, который был использован при конструировании записи. Hе забудьте удалить символы пробела, добавленные при заподнении полей. Обсуждение записи данных в файлы прямого доступа {5.4.5} содержит информацию, которая поможет Вам лучше понять информацию данного раздела.
Средний уровень.
Метод 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 | ;проверка на ошибку |
<~-5.4.5 Запись в файлы прямого доступа.
Содержание
5.4.7 Проверка данных после операций чтения/записи.-~>