5.4.4 Чтение из последовательных файлов.

Error message

Notice: Undefined index: add term path in hansel_get_breadcrumbs() (line 524 of /data/sites/msdosworld.ru/www/sites/all/modules/hansel/hansel.module).

  Чтение из последовательного файла мало чем отличается от запи-
си в него, за исключением того, что  процесс обратный.  В Бейсике
данные берутся из файла и присваиваются отдельным переменным  или
элементам массива данных. В  языке ассемблера данные помещаются в


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

   Высокий уровень.

   Чтение последовательных файлов в Бейсике проще, чем их запись,
поскольку  имеется только две возможности, как обращаться с ними,
в зависимости от того, какие  символы  в файле используются в ка-
честве ограничителей элементов данных. Оператор INPUT# распознает
запятые и  кавычки,  как  разделители  данных,  так же как и пары
возврат каретки/перевод строки.  Оператор LINE INPUT#  распознает
только  комбинации  CR/LF,  поэтому  он  может использоваться для
чтения  целых строк текста, содержащих другие ограничители.   Эта
возможность удобна при обработке текстов.
   Для чтения трех элементов оператором  INPUT#, сначала откройте
файл,  как обсуждалось в [5.3.3] (например, OPEN  "A:NEWSEQ"  FOR
INPUT AS #1). Если файл  был  открыт  под  номером 1, то оператор
INPUT  #1,  X$, Y$, Z$ присвоит значение  первых  трех  элементов
данных трем строковым переменным.  При вводе числовых переменных,
например,  INPUT  #1, X, Y, Z необходимо,  чтобы  соответствующие
данные в файле были числовыми.   Число с двойной точностью должно
считываться  в переменную двойной точности, с тем чтобы она могла
хранить восемь байтов такого  числа.  Другой способ прочитать три
элемента данных состоит в размещении их в массиве:

100 DIM ITEM$(40)       'создаем массив строк из 40 элементов
110 FOR N = 0 TO 39     'для каждого элемента
120 INPUT #1, ITEM$(N)  'считываем его и помещаем в массив
130 NEXT                '

Чтобы  прочитать n-ный элемент последовательного файла  программа
должна прочитать все  предшествующие  ему  элементы.  Надо просто
создать цикл, в котором будут считываться элементы данных, но  не
сохранять эти данные по мере их появления.
   Оператор LINE INPUT# действует в основном аналогично оператору
INPUT#,  за исключением того, что он может принимать только  одну
переменную и это всегда  строковая  переменная.  Переменная может
быть  длиной до 254 символов и это максимально допустимый  размер
строковых переменных  в  Бейсике.   Пара  возврат каретки/перевод
строки,  содержащаяся в файле, включается в строку,  возвращаемую
оператором LINE INPUT#. Это свойство позволяет обнаруживать конец
параграфа в текстовом файле.
   Функция  EOF (конец файла) может быть использована для опреде-
ления того, все ли  элементы  файла  были  прочитаны. Эта функция
возвращает -1, если файл исчерпан и 0 - в противном случае. Функ-
ции требуется номер файла, под  которым  он был открыт; например,
если  был был открыт как #2, то X = EOF(2).  В следующем  примере
весь текстовый файл считывается в массив:

100 OPEN "TEXT.AAA" FOR INPUT AS #2   'открываем файл
110 DIM TEXT$(500)                    'не более 500 строк
120 LINECOUNT = 0                     'счетчик строк


130 LINE INPUT #2, TEXT$(LINECOUNT)   'получаем строку
140 IF EOF(2) THEN 170                'проверка на конец файла
150 LINECOUNT = LINECOUNT + 1         'увеличиваем счетчик
160 GOTO 130                          'на следующую строку
170 ...                               'файл прочитан

   Оператор INPUT$ читает  из  последовательного  файла указанное
число символов.  На самой программе лежит забота о выделении  от-
дельных элементов  данных.  Формат  этого оператора для чтения 30
символов  из файла #1 такой: S$ = INPUT$(30,#1).  Хотя Вы  можете
указывать число байт для  чтения,  необходимо  чтобы это число не
превосходило  254,  поскольку это максимальный  размер  строковой
переменной, в которую помещаются данные. INPUT$ полезен при пере-
даче массы данных в непрерывную область памяти.  Например, в сле-
дующем примере делается дамп  первых 200 байтов последовательного
файла в буфер монохромного дисплея, с тем чтобы они были выведены
на экран, включая управляющие коды:

100 OPEN "A:NEWFILE" FOR INPUT AS #1   'открываем файл
110 CLS: DEF SEG = &HB000              'указываем на буфер
120 FOR N = 0 TO 9                     'получаем 10 групп
130 S$ = INPUT$(20,#1)                 'по 20 байтов
140 FOR M = 1 TO 20                    'берем каждый байт
150 POKE N*160 + M*2, ASC(MID$(S$,M,1) 'и помещаем его в буфер
160 NEXT M       'переход к следующему байту
170 NEXT N       'переход к следующей группе

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

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

Метод FCB:
   Функция 14H прерывания 21H читает последовательные файлы. Надо
создать управляющий блок  файла  и  область  обмена с диском, как
объяснено в [5.3.5].  Файл должен быть открыт функцией 0FH преры-
вания 21H [5.3.3].   DS:DX  должны  указывать на первый байт FCB,
после  чего функция 14H будет читать по одной записи из файла при
каждом вызове.  Вы можете установить размер записи по смещению 14
в FCB.  Это надо делать после того, как файл открыт, так как  при
открытии файла DOS вставляет  в  это  поле значение по умолчанию,
равное 128.

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


каждой записи указатель увеличивать на размер записи, с тем чтобы
он указывал на место, где должна быть следующая запись.
   Установкой полей  текущей  записи  (DB,  смещение 1FH) и блока
текущей  записи (DW, смещение 0CH) отличными от нуля,  последова-
тельный может читаться,  начиная  с  любого требуемого места (ус-
тановка  должна быть сделана после открытия FCB).  После  каждого
чтения поле текущей записи  автоматически  увеличивается  на 1, а
после  чтения 128 записей увеличивается поле текущего блока.  При
возврате AL равен 0, если вся запись успешно прочитана. При обна-
ружении конца файла AL будет содержать 1, если функция 14H вообще
не возвратила данных и 3 - если запись прочитана частично.
   В приведенном примере из файла считываются две записи и после-
довательно  помещаются  в нужную область памяти.   Размер  записи
установлен равным 256 байтам.  Записи считываются в цикле и после
того,  как  первая  запись считана, указатель на  DTA  изменяется
таким образом, чтобы он  указывал  на следующий пустой байт в об-
ласти данных.

;---помещаем FCB в сегмент данных
FCB          DB  0,'OLDDATA DAT', 25 DUP(0)
DATA_AREA    DB  512 DUP (?)    ;используем как DTA

;---устанавливаем DTA на начало области данных
   LEA  DX,DATA_AREA      ;DS:DX указывают на DTA
   MOV  DI,DX             ;сохраняем копию
   MOV  AH,1AH            ;функция установки DTA
   INT  21H               ;устанавливаем DTA
;---открываем файл
   LEA  DX,FCB            ;DS:DX указывают на FCB
   MOV  AH,0FH            ;функция открытия файла
   INT  21H               ;открываем файл
   CMP  AL,0              ;проверка на ошибку
   JNE  OPEN_ERROR        ;
;---устанавливаем размер записи 256 байт
   LEA  BX,FCB            ;DS:DX указывают на FCB
   MOV  AX,256            ;размер записи
   MOV  DS:[BX]+14,AX     ;посылаем в поле размера записи
;---чтение данных
   MOV  CX,2              ;число читаемых записей
NEXT_REC:   MOV  AH,14H   ;функция чтения файла
   LEA  DX,FCB            ;DS:DX указывают на FCB
   INT  21H               ;читаем одну запись
   CMP  AL,0              ;все в порядке?
   JE   CONTINUE          ;
   CMP  AL,2              ;проверка на ошибку
   JE   READ_ERROR        ;
    .
    .

CONTINUE:  ADD  DI,256    ;увеличиваем указатель
   MOV  DX,DI             ;DX указывает на новую DTA
   MOV  AH,1AH            ;функция установки DTA
   INT  21H               ;устанавливаем DTA


   LOOP NEXT_REC          ;идем на чтение следующей записи
;---позднее, закрываем файл
   LEA  DX,FCB            ;DS:DX указывают на FCB
   MOV  AH,10H            ;функция закрытия файла
   INT  21H               ;закрываем файл
   CMP  AL,0FFH           ;проверка на ошибку
   JE   CLOSE_ERROR       ;

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


увеличивает размер программы на диске.   В своих программах лучше
создавать буфер, используя технику распределения памяти,  описан-
ную в [1.3.1].

;---в сегменте данных
PATH        DB   'A:FILENAME.EXT'0   ;строка пути к файлу
DATA_BUFFER DB   1000 DUP (?)        ;буфер данных
HANDLE      DW   ?                   ;номер файла
FILESIZE    DW   ?                   ;размер файла

;---открываем файл
   LEA  DX,PATH            ;DS:DX указывают на путь
   MOV  AL,0               ;код открытия для чтения
   MOV  AH,3DH             ;функция открытия файла
   INT  21H                ;открываем файл
   JC   OPEN_ERROR         ;проверка на ошибку
   MOV  HANDLE,AX          ;запоминаем номер файла
;---устанавливаем файловый указатель на конец файла
   MOV  AH,42H             ;функция установки указателя
   MOV  AL,2               ;код для конца файла
   MOV  BX,HANDLE          ;номер файла
   MOV  CX,0               ;смещение равно нулю
   MOV  DX,0               ;
   INT  21H                ;устанавливаем указатель
   JC   POINTER_ERROR1     ;обработка ошибки
   MOV  FILESIZE,AX        ;запоминаем размер (меньше 64K)
;---возвращаем указатель на начало
   MOV  AH,42H             ;номер функции
   MOV  AL,0               ;код для начала файла
   MOV  CX,0               ;смещение равно нулю
   MOV  DX,0               ;
   INT  21H                ;устанавливаем указатель
   JC   POINTER_ERROR2     ;обработка ошибки

;---читаем весь файл
   MOV  AH,3FH             ;номер функции чтения файла
   MOV  BX,HANDLE          ;номер файла
   MOV  CX,FILESIZE        ;число считываемых байтов
   LEA  DX,DATA_BUFFER     ;DS:DX указывают на буфер
   INT  21H                ;читаем файл
   JC   READ_ERROR         ;обработка ошибки

;---позднее, закрываем файл
   MOV  BX,HANDLE          ;номер файла
   MOV  AH,3EH             ;функция закрытия файла
   INT  21H                ;закрываем файл
   JC   CLOSE_ERROR        ;обработка ошибки
 

Вы находитесь в разделе: 

Добавить коментарий