Глава 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 Проверка данных после операций чтения/записи.-~>