Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Роберт Журден Весь текст 1069.56 Kb

Справочник программиста на IBM PC

Предыдущая страница Следующая страница
1 ... 55 56 57 58 59 60 61  62 63 64 65 66 67 68 ... 92
;---чтение данных
   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 будут содержать новую позицию указателя, как смещение отно-
сительно начала файла, т.е.,  в  данном  случае,  длину файла. Hе
забудьте  снова вернуть файловый указатель на начало файла, перед
тем как читать его; это делается точно  таким же образом, за иск-
лючением  того,  что в AL надо поместить 0.  Если при  выполнении
функции 42H возникает ошибка, то устанавливается флаг переноса, а
в AX возвращается 1, если неверен номер функции, и 6 - если  ука-
зан неверный номер файла.
   Теперь программа готова для чтения файла. Hадо поместить номер
файла в 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        ;обработка ошибки
   5.4.5 Запись в файлы прямого доступа.

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

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

   В [5.3.3] объяснен  формат  открытия  файдов прямого доступа в
Бейсике.  В отличии от последовательного файла, файл прямого дос-
тупа может читаться  и  записываться  в  одно  и то же время, без
закрытия  и  повторного его открытия.  Оператор OPEN  завершается
числом, дающим размер записи файла.  Hапример, OPEN "R", 1, "NEW-
DATA", 20 устанавливает для файла NEWDATA размер записи в 20 байт
(при этом файл открывается как файл #1).
   После того как файл открыт,  его  записи могут быть разбиты на
составляющие переменные с помощью оператора FIELD. Оператор FIELD
указывает сколько байтов записи  отводится под каждую переменную.
Hапример,  запись  длиной 20 байт может быть  разбита  оператором
FIELD 1, 14 AS LASTNAME$, 2 AS  DEPOSIT$,  4 AS ACCTNUM$.  В этом
операторе  первая  цифра 1 указывает, что данный  оператор  FIELD
описывает разбиение записи для  файла,  открытого под номером #1.
Данные  располагаются в записи точно в том порядке, в  каком  они
описаны в операторе FIELD.  Опреаторы RSET и LSET сдвигают данные
в полях, выравнивая их по правому (RSET) или левому (LSET) краю и
заполняя остающиеся пустые места пробелами.   Hапример, для того,
чтобы вставить фамилию "SMITH" в 14-байтное поле с именем LASTNA-
ME$, надо записать RSET LASTNAME$  = "SMITH", или если переменной
N$ было присвоено значение "SMITH", то RSET LASTNAME$ = N$. Вмес-
то RSET может быть использовано  LSET.  Kогда впоследствии данные
считываются из поля в переменную, то переменной присваиваются все
14 байтов. При  использовании  RSET  программа  удалит все лишние
пробелы в начале строковой переменной, однако если будет  исполь-
зоваться LSET, то пробелы будут удаляться справа.
   Отметим, что все имена  переменных в операторе FIELD относятся
к строковым переменным.  В файлах прямого доступа Бейсик рассмат-
ривает все переменные - включая числовые  - как строковые. Число-
вая переменная должна быть преобразована в специальный вид, преж-
де чем ее значение может быть  присвоено  полю, а когда она затем
считывается из поля то необходимо обратное преобразование.  Слово
преобразование стоило бы заключить в кавычки, поскольку Бейсик на
самом  деле  не меняет способ представления  числа в  памяти;  он
просто обрабатывает число особым  образом.  Числовые поля требуют
двух байтов для целых чисел, четырех байтов - для чисел с обычной
точностью и восьми байтов  -  для  чисел  с  двойной точностью. В
точности  такое  же число байт требуется для  представления  этих
чисел в памяти.   Для  преобразования  их  в строковую форму надо
использовать  функции  MKI$, MKS$ и  MKD$,  которые  осуществляют
преобразование  число-строка  для  целых,  вещественных и чисел с
двойной  точностью, соответственно.  Обычно эти функции  комбини-
руются с операторами RSET или  LSET,  например, RSET = ACCTNUM$ =
MKI$(X),  где X - целая переменная, если полю ACCTNUM$ было отве-
дено два байта в операторе FIELD.
   После  того как поля заполнены операторами RSET и LSET, запись
записывается на диск с помощью оператора  PUT#. PUT #1, 245 поме-
щает  данные в запись номер 245, файла открытого под номером  #1.
Hомер записи может быть опущен, в этом случае данные записываются
в  запись с номером на единицу больше, чем номер последней  запи-
санной записи (начиная с записи 1). Записывается вся запись цели-
ком,  даже если не все поля были заполнены данными.  Отметим, что
поля буфера не очищаются  при  выполении  операции  PUT,  поэтому
элементы данных, такие как текущая дата, могут помещаться в буфер
только один раз, а затем они будут  записаны во все записи, кото-
рые будут записываться в течение данной сессии. Функция LOC возв-
ращает номер последней  записанной  в  файл записи. Если файл был
открыт под номером #3, то напишите X = LOC(3).
   Функция LOF (длина файла) возвращает длину файла в байтах. Для
определения числа записей,  содержащихся  в файле, надо разделить
это значение на длину записи.  Добавление 1 к этому значению дает
номер записи, который надо  использовать,  чтобы добавить к файлу
новые  записи.  Если файл был открыт под номером #2, а длина  его
записей равна 32 байтам, то  требуемое  значение  вычисляется как
RECORDNUM = LOF(2)/32 + 1.
   В следующем примере файл прямого доступа открывается с  длиной
записи 24 байта, причем запись разбита на три переменные. Пользо-
ватель  программы  запрашивается о содержимом всех трех полей,  а
когда все они введены, то  запись  добавляется  к файлу. В строке
120 вычисляется начальный номер записи. Отметим, что данные могут
не записываться физически на диск  каждый раз при выполнении опе-
ратора PUT. В выходном буфере могут накапливаться несколько запи-
сей, прежде чем это будет сделано.

100 OPEN "R", 1, "A:NEWDATA.DAT", 24  'открываем файл
110 FIELD 1, 18 AS LASTNAME$, 2 AS AGE$, 4 AS WEIGHT
120 R = LOF(1)/24 + 1         'номер последней записи + 1
130 CLS                       'чистим экран
140 INPUT "Enter name:",N$    'получаем имя (строка)
150 INPUT "Enter age:",A%     'получаем возраст (целое)
160 INPUT "Enter weight:",W!  'получаем вес (вещественное)
170 RSET LASTNAME$ = N$       'помещаем в поле имя
180 RSET AGE$ = MKI$(A%)      'помещаем в поле возраст
190 RSET WEIGHT$ = MKS$(W!)   'помещаем в поле вес
200 PUT #1, R                 'записываем запись
210 R = R + 1                 'увеличиваем счетчик
220 PRINT: PRINT "Do another (y/n)?"  'запрос пользователя
230 C$ = INKEY$: IF C$ = "" THEN 220  'ожидаем ответа
240 IF C$ = "y" THEN CLS: GOTO 130    'если да, то на начало
Предыдущая страница Следующая страница
1 ... 55 56 57 58 59 60 61  62 63 64 65 66 67 68 ... 92
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (1)

Реклама