нал. Таким образом PRINT #1, A$, B$ отделяет B$ от A$, в то время
как PRINT #1, A$; B$ - нет; файл будет добавляться нужным числом
пробелов. Оператор PRINT# может быть испоьзован в форме PRINT #1
USING..., где могут быть использованы все обычные экранные форма-
ты PRINT USING для форматирования вывода в файл.
Вообще говоря, более экономично использовать оператор PRINT#,
записывая каждый раз по одной переменной. Этот метод избавляет от
излишних ограничителей и позволяет затем безошибочно считывать
строки любого вида. Более сложные схемы ограничителей, используе-
мые при записи нескольких переменных одним оператором PRINT# или
WRITE# могут привести к проблемам, особенно если одна переменная
будет считана как две, что приведет к потере текущей позиции в
файле.
После того как все данные будут записаны в файл, просто зак-
ройте его, чтобы обезопасить содержащиеся в нем данные. Напишите
CLOSE, чтобы закрыть все открытые файлы, CLOSE #1 - чтобы закрыть
файл #1 и CLOSE #1, #3 - чтобы закрыть файлы #1 и #3. Хотя в
некоторых случаях Бейсик прощает незакрытые файлы, но это не тот
случай. Операторы WRITE# и PRINT# выводят данные в файловый бу-
фер, который записывается на диск только тогда, когда они запол-
нены информацией. Последние введенные данные записываются на диск
оператором CLOSE. Отсутствие этого оператора может привести к
потере данных. Вот пример:

100 OPEN "A:NEWSEQ" FOR OUTPUT AS #1 'открываем файл


110 A$ = "aaaaa" 'готовим три строки
120 B$ = "bbbbb" '
130 C$ = "ccccc" '
140 WRITE #1, A$, B$, C$ 'запись строк
150 CLOSE 'очистка буфера

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

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

Метод FCB:
Функция 15H прерывания 21H предназначена для записи в последо-
вательный файл. Надо подготовить управляющий блок файла и область
обмена с диском, как показано в [5.3.5]. Если файл должен быть
перезаписан, то его надо открыть с помощью функции 16H, которая
"создает" файл, обрезая его до нулевой длины. Если Вы откроете
файл с помощью функции 0FH, то остаток старого файла останется в
конце файла, если длина нового файла будет меньше, чем старого. С
другой стороны, если Вы хотите добавить данные к файлу, то ис-
пользуйте функцию открытия файла.
После того как файл открыт, Вы должны установить DS:DX на
начало FCB и вызвать функцию 15H для того чтобы заприсать одну
запись данных. Количество данных в записи зависит от величины,
которая помещена в поле длины записи, расположенное со смещением
14 в обычном FCB, по умолчанию это значение равно 128 байтам.
Если размер записи меньше, чем размер сектора диска 512 байт, то
данные будут буферизоваться, до тех пор пока не накопится доста-
точно данных, чтобы произвести реальную запись на диск; поэтому
записи в последовательный файл могут успешно записываться даже
если накопитель не включен. При закрытии файла все данные остав-
шиеся в буфере сбрасываются на диск. При возврате из функции 15H,
AL равен 0, если операция успешна, 1 - если диск полон и 2 - если
сегмент области обмена данных слишком мал.
В следующем примере на диск записываются 5 записей длиной 256
байтов. Записи могут быть набором текстовых данных. Эти данные
расположены в области памяти, помеченной меткой WORKAREA. Указа-
тель на DTA первоначально устанавливается на начало этой области,
а после записи каждой записи установка DTA меняется таким обра-
зом, чтобы он указывал на 256 байтов выше. Отметим, что обычно
для такой рабочей области отводится специальная область памяти
[1.3.1], но в данном примере для простоты используется буфер
расположенный в сегменте данных.


;---в сегменте данных
WORKAREA DB 2000 DUP (?) ;буфер данных
FCB DB 1,'FILENAMEEXT',25 DUP (0)

;---DTA должен указывать на рабочую область
LEA DX,WORKAREA ;DS:DX указывают на DTA
MOV DI,DX ;сохраняем копию
MOV AH,1AH ;функция установки DTA
INT 21H ;устанавливаем DTA
;---открываем файл
MOV AH,16H ;номер функции
LEA DX,FCB ;DS:DX указывают на FCB
INT 21H ;открываем файл
;---устанавливаем размер записи
LEA BX,FCB ;BX указывает на FCB
MOV AX,256 ;размер записи 256 байтов
MOV [BX]+14,AX ;записываем в поле размера записи
;---посылаем данные в файл
MOV CX,5 ;число записей
NEXT_REC: MOV AH,15H ;функция записи
LEA DX,FCB ;указываем на FCB
INT 21H ;записываем данные
CMP AL,2 ;проверка на ошибки
JE CONTINUE ;и их обработка
CMP AL,1 ;
JE DISK_FULL ;
;---перенос выполнен, переустанавливаем DTA
ADD DI,256 ;сдвигаемся на 1 запись
MOV DX,DI ;DS:DX указывают на новый DTA
MOV AH,1AH ;функция установки DTA
INT 21H ;установка новой позиции
LOOP NEXT_REC: ;идем на следующую запись

;---позднее, закрываем файл
LEA DX,FCB ;DS:DX указывают на FCB
MOV AH,10H ;функция закрытия файла
INT 21H ;закрываем файл

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

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


функция используется для записи в файл прямого доступа, то при
закрытии файла его длина не устанавливается равной последней
позиции файлового указателя. Возьмем, например, случай, когда
текстовый файл размером 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 ;


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



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


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

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

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


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



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


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

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

В [5.3.3] объяснен формат открытия файдов прямого доступа в
Бейсике. В отличии от последовательного файла, файл прямого дос-
тупа может читаться и записываться в одно и то же время, без
закрытия и повторного его открытия. Оператор OPEN завершается
числом, дающим размер записи файла. Например, OPEN "R", 1, "NEW-
DATA", 20 устанавливает для файла NEWDATA размер записи в 20 байт
(при этом файл открывается как файл #1).
После того как файл открыт, его записи могут быть разбиты на
составляющие переменные с помощью оператора FIELD. Оператор FIELD
указывает сколько байтов записи отводится под каждую переменную.
Например, запись длиной 20 байт может быть разбита оператором
FIELD 1, 14 AS LASTNAME$, 2 AS DEPOSIT$, 4 AS ACCTNUM$. В этом
операторе первая цифра 1 указывает, что данный оператор FIELD
описывает разбиение записи для файла, открытого под номером #1.
Данные располагаются в записи точно в том порядке, в каком они
описаны в операторе FIELD. Опреаторы RSET и LSET сдвигают данные
в полях, выравнивая их по правому (RSET) или левому (LSET) краю и
заполняя остающиеся пустые места пробелами. Например, для того,
чтобы вставить фамилию "SMITH" в 14-байтное поле с именем LASTNA-
ME$, надо записать RSET LASTNAME$ = "SMITH", или если переменной
N$ было присвоено значение "SMITH", то RSET LASTNAME$ = N$. Вмес-
то RSET может быть использовано LSET. Когда впоследствии данные
считываются из поля в переменную, то переменной присваиваются все
14 байтов. При использовании RSET программа удалит все лишние
пробелы в начале строковой переменной, однако если будет исполь-
зоваться LSET, то пробелы будут удаляться справа.
Отметим, что все имена переменных в операторе FIELD относятся
к строковым переменным. В файлах прямого доступа Бейсик рассмат-
ривает все переменные - включая числовые - как строковые. Число-
вая переменная должна быть преобразована в специальный вид, преж-
де чем ее значение может быть присвоено полю, а когда она затем
считывается из поля то необходимо обратное преобразование. Слово
преобразование стоило бы заключить в кавычки, поскольку Бейсик на
самом деле не меняет способ представления числа в памяти; он
просто обрабатывает число особым образом. Числовые поля требуют
двух байтов для целых чисел, четырех байтов - для чисел с обычной
точностью и восьми байтов - для чисел с двойной точностью. В