Глава 5. Дисковые накопители.

Раздел 4. Чтение и запись файла.

5.4.5 Запись в файлы прямого доступа.

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

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

Kак и все другие операции с файлами в MS DOS имеется два метода записи в файл прямого доступа, один с использованием управляющего блока файла, а другой с помощью дескриптора файла. В обоих случаях Вы должны создать буфер обмена данными, размер которого должен быть не меньше, чем размер записи. Метод управляющего блока файла:

Откройте управляющий блок файла с помощью функции 0FH и пусть DS:DX указывают на него. После того как файл открыт поместите номер записи для прямого доступа в поле записи прямого доступа FCB. Затем вызовите функцию 22H прерывания 21H, которая пердаст данные из DTA в файловый буфер, созданный при создании FCB. Данные могут не быть немедленно записаны на диск, если размер записи меньше чем размер буфера. Реальная запись на диск будет происходить тогда, когда очередной вызов функции 22H заполнит буфер.

При возврате из функции 22H AL будет содержать 00, если обмен прошел успешно. В противном случае в нем будет 1, если не хватает пространства на диске и 2 - если область переноса мала для того, чтобы записать одну запись (т.е. если размер буфера, установленный системой меньше, чем тот, который указан в FCB).
;---в сегменте данных
FCB DB 1, 'NEWDATA ', 25 DUP (0)
DTA DB 256 DUP (?)
;---открываем файл и устанавливаем поля FCB
MOV AH,0FH ;номер функции
LEA DX,FCB ;DS:DX указывают на FCB
MOV BX,DX ;копируем смещение для FCB
INT 21H ;открываем файл
MOV AX,256 ;размер записи
MOV [BX]+14,AX ;помещаем в поле размера записи
MOV AX,233 ;номер записи
MOV [BX]+33,AX ;помещаем в поле номера записи
MOV AX,0 ;обнуляем старший байт этого слова
MOV [BX]+35,AX ;
;---перенос данных из DTA в файл
MOV AH,22H ;номер функции записи с прямым доступом
LEA DX,FCB ;DS:DX указывают на FCB
INT 21H ;записываем данные
CMP AL,0 ;проверка на ошибку
JNE WRITE_ERROR ;
;---позднее, закрываем файл
LEA DX,FCB ;DS:DX указывают на FCB
MOV AH,10H ;функция закрытия файла
INT 21H ;закрываем файл
CMP AL,0FFH ;проверка на ошибку
JE CLOSE_ERROR ;

Часто программа работает сразу с набором записей прямого доступа, передавая их в память и из памяти как единое целое. MS DOS предоставляет специальную функцию для этого при использовании метода FCB, называемую запись блока с прямым доступом. Это функция 28H прерывания 21H. При входе DS:DX должны указывать на открытый FCB, в котором поле записи прямого доступа должно быть равно номеру первой из записываемых записей набора. Эта функция совершенно аналогична вышеприведенному примеру. Единственное отличие (кроме номера функции) состоит в том, что в CX должно быть указано число записей в блоке (не путайте эти "блоки" с блоками по 128 записей, с помощью которых система находит требуемую запись - программа может читать любое число записей, начиная с любого места).

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

При использовании для доступа метода дескриптора файлов система не различает последовательные файлы и файлы прямого доступа. Ваша программа должна вычислить позицию в файле, с которой начинается требуемая запись, и установить на нее файловый указатель. Файловый указатель позиционируется с помощью функции 42H прерывания 21H. Поместите номер файла в BX, а смещение в файле в CX:DX (CX будет содержать старший байт значения). Затем поместите в AL кодовый номер от 0 до 2. При AL = 0, указатель будет установлен со смещением CX:DX байтов относительно начала файла; при AL = 1, указатель будет установлен со смещением CX:DX относительно текущей позиции, а при AL = 2, указатель будет установлен со смещением CX:DX относительно конца файла (т.е. таким образом файл будет расширен). Отрицательные числа недопустимы в качестве смещений. При возврате DX:AX будут содержать новое положение указателя (старший байт в DX). Если устанавливается флаг переноса, то произошла ошибка. В этом случае AX будет содержать 1, если указан неверный код в AL и 6 - если указан неверный номер файла.

После позиционирования файлового указателя запись прямого доступа записывается с помощью той же функции 40H прерывания 21H, которая использовалась для записи в последовательный файл. При входе BX содержит номер файла, а CX - число байтов, которое надо записать. При возврате AX будет содержать число реально записанных байтов. Если оно отличается от числа помещенного в CX, то вероятно диск полон (см. {5.1.4}). Kак обычно, при возникновении ошибки устанавливается флаг переноса. В этом случае AX будет содержать 5 при ошибке накопителя и 6 - если указан неверный номер файла.

Файловый указатель играет ту же роль для образа файла на диске, что DTA для образа файла в памяти. Он может сдвигаться как угодно для доступа к различным частям файла. Будьте внимательны, манипулируя файловым указателем при работе с фалом прямого доступа, содержимое любого поля любой записи может быть сразу прочитано с диска и помещено в требуемое место в памяти.
;---в сегменте данных
HANDLE DW ? ;номер файла
FILEPATH DB 'A:NEWDATA',0 ;строка пути к файлу
REC_BUFFER DB 30 DUP (?) ;буфер выводимых записей
;---открываем файл
MOV AH,3DH ;номер функции
MOV AL,1 ;код открытия для записи
LEA DX,FILEPATH ;DS:DX указывают на путь
INT 21H ;открываем файл
JC OPEN_ERROR ;проверка на ошибку
MOV HANDLE,AX ;сохраняем номер файла
;---вычисляем позицию записи и устанавливаем файловый указатель
MOV AX,30 ;размер записи 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,40H ;номер функции
MOV BX,HANDLE ;номер файла
MOV CX,30 ;размер записи
LEA DX,REC_BUFFER ;DS:DX указывают на буфер
INT 21H ;пишем запись
JC WRITE_ERROR ;проверка на ошибку

В отличии от метода FCB метод дескриптора файлов не предоставляет специальной функции для записи блока записей прямого доступа. Однако Вашей программе необходимо только вычислить количество байтов, составляющих блок записей, которое должно быть записано.


<~-5.4.4 Чтение из последовательных файлов.
Содержание
5.4.6 Чтение из файлов прямого доступа.-~>

Сайт управляется системой uCoz