File Reading

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

Hello World!

Вывод:

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.