Страница 38 из 41 Средний уровень. Как и все другие операции с файлами в 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 метод дескриптора файлов не предостав- ляет специальной функции для записи блока записей прямого досту- па. Однако Вашей программе необходимо только вычислить количество байтов, составляющих блок записей, которое должно быть записано.
|