Справочник программиста на персональном компьютере фирмы IBM. Дисковые накопители - Запись в последовательные файлы. Часть 3

ОГЛАВЛЕНИЕ



Метод дескриптора файла:
   Необходима  внимательность  при открытии файла для  последова-
тельного вывода методом дескриптора  файла. Поскольку та же самая

функция  используется для записи в файл прямого доступа,  то  при
закрытии файла его  длина  не  устанавливается  равной  последней
позиции  файлового указателя.  Возьмем, например,  случай,  когда
текстовый файл размером 2000  байтов считывается с диска, а затем
в процессе обработки в памяти его длина уменьшается до 1000 байт.

Если файл был открыт  простой  командой  открытия  файла (функция
3DH),  то  после того, как новая, более  короткая,  версия  файла
будет записана на диск и файл  будет  закрыт, его длина останется
равной 2000 байтам, из которых новый текст будет занимать  первую
тысячу байтов. По этой  причине,  при  открытии последовательного
файла для перезаписи надо использовать функцию 3CH прерывания 21H
[5.3.2].  Эта функция обычно создает новый файл, но если файл уже
существует, то он  обрезается  до  нулевой  длины. Для добавления
данных  в последовательный файл надо использовать обычную функцию
открытия файла, 3DH прерывания 21H [5.3.3].
   Рассмотрим сначала случай полной перезаписи файла. После того,
как файл открыт функцией 3CH, файловый указатель  устанавливается
равным нулю, поэтому нет нужды устанавливать его. Поместите номер
файла  в BX, а число записываемых байтов в CX.  Затем  установите
DS:DX на первый байт  выводимых  данных  и  выполните функцию 40H
прерывания 21H.  При возврате, если флаг переноса установлен,  то
была ошибка и AX содержит 5, если была ошибка дискового накопите-
ля и 6 - если неверный номер файла.  В противном случае, AX будет
содержать число реально  записанных  байтов; при несовпадении ве-
роятнее всего проблема состоит в том, что диск полон. Не забудьте
о процедуре восстановления при сбоях, так как при крахе программы
первоначальное  содержимое  файла будет утеряно, так как  он  был
обрезан до нулевой длины.  Как  проверять  дисковое  пространство
описано в [5.1.2]. Вот пример:

;---в сегменте данных
PATH         DB    'B:FILENAME.EXT',0   ;путь к файлу
DATA_BUFFER  DB    2000 DUP (?)

;---открываем файл с помощью функции "создания"
   LEA  DX,PATH          ;DS:DX указывают на путь к файлу
   MOV  CX,0             ;атрибуты файлы (здесь обычные)
   MOV  AH,3CH           ;номер функции
   INT  21H              ;открываем файл
   JC   OPEN_ERROR       ;проверка на ошибку
   MOV  HANDLE,AX        ;запоминаем номер файла
;---записываем в файл 1000 байтов
   MOV  AH,40H           ;номер функции
   MOV  BX,HANDLE        ;номер файла в BX
   MOV  CX,1000          ;число байт, которые надо записать
   LEA  DX,DATA_BUFFER   ;DS:DX указывают на буфер данных
   INT  21H              ;записываем данные
   JC   OUTPUT_ERROR     ;проверка на ошибки
   CMP  CX,2000          ;и их обработка
   JNE  FULL_DISK        ;

   Для  добавления записей в последовательный файл  надо  открыть
файл с помощью функции 3DH  прерывания  21H, помещая 1 в AL, если
программа будет только писать данные и 2, если программа будет  и
читать и писать. Длина файла  остается  неизменной, хотя он будет
увеличиваться по мере добавления данных.  Файловый указатель дол-
жен быть установлен на  конец  файла,  иначе  существующие данные
будут перезаписаны.  Это выполняется функцией 42H прерывания 21H.
Поместите номер подфункции 2  в  AL,  для  установки указателя на
конец  файла,  а номер файла поместите в BX.  CX:DX указывают  на
смещение  относительно  конца  файла,  начиная  с  которого будет
производиться запись, поэтому обнулите эти регистры. Затем выпол-
ните функцию установки указателя. При возврате установленный флаг
переноса  индицирует  ошибку, при этом в AX будет 1,  если  номер
подфункции в AL был неверен, и 6  - если неверно был указан номер
файла.   После  того как файловый указатель  установлен  операция
записи выполняется в точности как в предыдущем случае:

;---в сегменте данных
PATH          DB  'B:FILENAME.EXT',0   ;путь к файлу
DATA_BUFFER   DB  1000 DUP(?)

;---открываем файл
   LEA  DX,PATH       ;DS:DX указывают на путь
   MOV  AL,1          ;код открытия только для записи
   MOV  AH,3DH        ;номер функции
   INT  21H           ;открываем файл
   JC   OPEN_ERROR    ;уход по ошибке
   MOV  HANDLE,AX     ;сохраняем номер файла
;---установка файлового указателя на конец файла
   MOV  BX,AX         ;номер файла в BX
   MOV  CX,0          ;CX:DX дают смещение относительно конца
   MOV  DX,0          ;
   MOV  AL,2          ;код для конца файла
   MOV  AH,42H        ;функция установки указателя
   INT  21H           ;устанавливаем указатель
   JC   POINTER_ERROR ;проверка на ошибку
;---добавляем к файлу 300 байтов
   MOV  AH,40H        ;номер функции
   MOV  BX,HANDLE     ;номер файла в BX
   MOV  CX,300        ;число записываемых байтов
   LEA  DX,DATA_BUFFER   ;DS:DX указывают на буфер данных
   INT  21H           ;добавляем данные
   JC   OUTPUT_ERROR  ;проверка на ошибки
   CMP  CX,300        ;и их обработка
   JNE  FULL_DISK     ;