Следующая программа считывает файл 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.