Следующая программа считывает файл a.txt
и выводит содержащиеся в
нём байты в виде целых чисел.
MODULE FileTest;
IMPORT Out, Files;
VAR F: Files.File; (*это указатель*)
r: Files.Rider; (*а это запись (record) *)
c: CHAR;
BEGIN
F := Files.Old('a.txt');
IF F = NIL THEN
Out.String('Файл не удалось открыть.'); Out.Ln
ELSE
Out.String('Содержимое файла:'); Out.Ln;
Files.Set(r, F, 0); (*установить бегунок на начало файла*)
Files.Read(r, c); (*попытаться считать первый байт*)
WHILE ~r.eof DO (*пока файл не закончился*)
Out.Int(ORD(c), 4);
Files.Read(r, c) (*попытаться считать следующий байт*)
END;
Out.Ln
END
END FileTest.
Содержимое файла a.txt
:
Вывод:
72 101 108 108 111 32 87 111 114 108 100 33
F
— переменная, обозначающая файл.
Процедура Old
открывает файл и возвращает (указатель на) объект типа File
.
F := Files.Old('a.txt')
Если файл не удалось открыть, то возвращается NIL (указатель никуда).
r
— бегунок по файлу, чтение и запись происходит через него.
Бегунок надо сначала прицепить к файлу. Это делает процедура Set:
Files.Set(r, F, 0)
Здесь 0
— это позиция в файле F
, на
которую устанавливается бегунок. Мы хотим встать на начало файла,
поэтому указываем нуль.
Для чтения одного байта из файла используется процедура Read
:
Files.Read(r, c)
Прочитанный байт помещается в переменную c
. Бегунок
r
автоматически перемещается по файлу правее на один байт.
При этом r.eof
устанавливается в FALSE
.
(r
— это RECORD
, а
eof
— это BOOLEAN
внутри него).
Если же при вызове Read
оказывается, что файл закончился (строго
говоря — бегунок стоит за концом файла), то булево поле r.eof
устанавливается в TRUE
.
~
— это логическое отрицание.
WHILE условие DO действие END
— обыкновенный цикл WHILE.
Out.String, Out.Int, Out.Ln
— вывод строки, целого числа и перенос строки.
Второй параметр Out.Int
— это минимальная ширина (в литерах), которую будет
занимать число на экране (дополняется пробелами слева).
ORD
— это встроенная функци, которая принимает значение типа CHAR и
возвращает значение типа INTEGER
— код данной литеры. На машинном
уровне в этот момент
не происходит ничего: как было число, так и осталось, но логически тип сменяется с
CHAR
на INTEGER
. Обратная к
ORD
функция называется CHR
.
Для любого c
типа CHAR
верно, что
c =
.
CHR
(ORD
(c))
Примечание:
При обращении к любым находящимся в других модулях объектам всегда
указывается название модуля.
Поэтому не F := Old('a.txt')
, а
F := Files.Old('a.txt')
.
При импорте модуля можно локально сменить его название:
IMPORT Out, F := Files;
И тогда везде будет F.Set
, F.Old
, F.Read
.