Файл: jourdain_spravochnik_programmista.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.07.2020

Просмотров: 3148

Скачиваний: 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 'если да, то на начало

250 CLOSE 'иначе закрываем файл


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


Как и все другие операции с файлами в 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 метод дескриптора файлов не предостав-

ляет специальной функции для записи блока записей прямого досту-

па. Однако Вашей программе необходимо только вычислить количество

байтов, составляющих блок записей, которое должно быть записано.



5.4.6 Чтение из файлов прямого доступа.




Чтение файлов прямого доступа является обратным процессом по

отношению к их записи. MS DOS вычисляет позицию в файле на диске,

затем считывает запись и помещает ее в память. Затем программа

должна разделить запись на поля в точности того же размера, кото-

рый был использован при конструировании записи. Не забудьте уда-

лить символы пробела, добавленные при заподнении полей. Обсужде-

ние записи данных в файлы прямого доступа [5.4.5] содержит инфор-

мацию, которая поможет Вам лучше понять информацию данного разде-

ла.



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


Для чтения файла прямого доступа необходимо открыть файл и

определить поля записи, как объяснено в разделе, относящемся к

записи в файлы прямого доступа. Затем надо использовать оператор

GET# для чтения определенной записи с диска. GET #1,23 считывает

запись номер #23 из файла, открытого под номером #1. При чтении

записи переменной, именованной в операторе FIELD, автоматически

присваивается соответствующее значение из записи. Например, если

оператор FIELD имеет вид FIELD 1, 20 AS X$, 2 AS Y$, то после

выполнения оператора GET 1,23 переменной X$ будет присвоено зна-

чение первых 20-ти байтов записи 23, а переменной Y$ - следующих

10-ти байтов. Операторы, аналогичные RSET и LSET для выделения

полей данных отсутствуют.

В случае числовых полей, напоминаем, что они должны быть

преобразованы в строковый вид с помощью функций MKI$, MKS$ и

MKD$. Для восстановления их оригинальных значений, с тем чтобы

над ними можно было проводить операции и печатать их, надо преоб-

разовать эти строки с помощью функций CVI, CVS и CVD. Если Y$

содержит целое число, то для выполнения обратного преобразования

запишите Y% = CVI(Y$), при этом переменная Y% будет содержать

значение, которое имела переменная перед тем как она была спе-

циально обработана для записи в файл прямого доступа. Если Вы

выведете строковое значение переменной, то увидите, что это число

в интервале от 0 до 65535, закодированное в два символа ASCII.

В данном примере открывается файл, созданный в примере пункта

[5.4.5], и выводится содержимое любой из затребованных записей:


100 OPEN "A:NEWDATA" AS #1 LEN = 24 'открываем файл

110 FIELD 1, 18 AS LASTNAME$, 2 AS AGE$, 4 AS WEIGHT$

120 CLS: INPUT "What is the record number";R 'запрос записи

130 IF R*24 > LOF(1) THEN BEEP: PRINT"No such record": GOTO 120

140 GET #1,R 'читаем запись из файла

150 PRINT LASTNAME$, CVI(AGE$), CVS(WEIGHT$) 'выводим ее

160 PRINT: PRINT "Do another (y/n)?" 'будем повторять?

170 C$ = INKEY$: IF C$ = "" THEN 170 'ожидаем ввода

180 IF C$ = "y" OR C$ = "Y" THEN 120 'повторяем, если надо

190 CLOSE 'иначе закрываем файл



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


Метод FCB доступа к файлам имеет две функции для чтения запи-

сей с прямым доступом. С другой стороны, метод дескриптора файлов

использует ту же функцию, что и для чтения последовательных фай-

лов. Два метода доступа рассматриваются отдельно.


Метод FCB:

Функция 21H прерывания 21H читает одну запись из файла прямого

доступа. Вторая функция, 27H, читает блок последовательных запи-

сей. Создайте управляющий блок файла, как показано в [5.3.5] и

откройте его [5.3.3]. После того как FCB открыт, введите в него

значения полей размера записи (DW по смещению 14) и номера записи

прямого доступа (DD по смещению 33). Если DS:DX указывают на



первый байт FCB, то можно вызывать функцию 21H для чтения записи

и запись будет помещена в паямть, начиная с первого байта DTA.

Если запись успешно прочитана, то в AL будет возвращен 0.

Однако при этом нет гарантии, что чтение прошло без ошибок, пос-

кольку неверный размер записи может привести к тому, что части

прилегающих записей будут считаны, как будто это одна запись.

Если запрошена запись с номером большим, чем число записей в

файле, то в AL будет возвращено 1 или 3. Если был возвращен код

3, то был считан самый конец файла и была прочитана часть записи

данных. Если был возвращен код 1, то данные вообще не были счита-

ны.

Данный пример считывает одну запись и помещает ее в DTA:


;---в сегменте данных

FCB DB 1,'OLDDATA ', 25 DUP (0)


;---открываем файл и устанавливаем поля FCB

MOV AH,0FH ;номер функции

LEA DX,FCB ;DS:DX указывают на FCB

MOV BX,DX ;копируем смещение FCB

INT 21H ;открываем файл

MOV AX,55 ;размер записи 55 байтов

MOV [BX]+14,AX ;помещаем в поле размера записи

MOV AX,22 ;номер записи для чтения

MOV [BX]+33,AX ;помещаем в поле номера записи

MOV AX,0 ;обнуляем старшее слово этого поля

MOV [BX]+35,AX ;

;---перенос данных из файла в DTA

MOV AH,21H ;номер функции чтения с прямым доступом

LEA DX,FCB ;DS:DX указывают на FCB

INT 21H ;читаем данные, помещая их в DTA

CMP AL,0 ;проверка на ошибку

JNE READ_ERROR ;

;---позднее, закрываем файл

MOV AH,10 ;номер функции закрытия файла

LEA DX,FCB ;DS:DX указывают на FCB

INT 21H ;закрываем файл


Для чтения блока последовательных записей в память за один

прием надо использовать функцию 27H прерывания 21H. Ее выполнение

подготавливается в точности так же, как и функции 21H, за исклю-

чением того, что вдобавок CX должен содержать число записей кото-

рые надо прочитать за один прием. При возврате CX будет содержать

число реально прочитанных записей. Значения возвращаемые в AL

совпадают с теми, которые возвращаеются функцией 21H. В отличии

от функции 21H поля FCB, в которых хранится информация о положе-

нии записи (поле записи прямого доступа, текущего блока и текущей

записи) автоматически увеличиваются, с тем чтобы они указывали на

следующую несчитанную запись после выполнения функции.