Справочник программиста на персональном компьютере фирмы IBM. Дисковые накопители - Запись в файлы прямого доступа. Часть 2
ОГЛАВЛЕНИЕ
Средний уровень.
Как и все другие операции с файлами в 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]). Как обычно, при возникновении
ошибки устанавливается флаг переноса. В этом случае 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 метод дескриптора файлов не предостав-
ляет специальной функции для записи блока записей прямого досту-
па. Однако Вашей программе необходимо только вычислить количество
байтов, составляющих блок записей, которое должно быть записано.