ZetCode

Algol 68 files

last modified November 13, 2026

A FILE value is a channel to a file on disk, a terminal, or a printer. A program opens a name with a channel that says whether it reads or writes, transputs values through the file, and closes it when it is done. This article describes opening, writing, reading, and closing files, reading every line of a file, and writing numbers and formatted reports that a later run can read back.

Writing a file

open(f, name, stand out channel) connects the variable f to the file called name for output, and creates the file if it does not exist. put and putf then write through the file, and close releases it.

writefile.a68
BEGIN
  STRING name = "notes.txt";
  FILE f;
  open(f, name, stand out channel);
  put(f, ("first line", newline));
  put(f, ("second line", newline));
  close(f);
  print(("wrote two lines to ", name, newline))
END

The FILE variable needs no initial value; open fills it in. Each put writes a row to the file, and the newline in the row separates the two lines. After close the file holds the text and the program reports the name it used.

$ a68g writefile.a68
wrote two lines to notes.txt

Reading a file back

The same name is opened with stand in channel for reading, and then get takes one line at a time. The string receives the characters without the newline, which the second item of the row consumes.

readfile.a68
BEGIN
  STRING name = "notes.txt";
  FILE f;
  open(f, name, stand out channel);
  put(f, ("alpha", newline));
  put(f, ("beta", newline));
  close(f);
  open(f, name, stand in channel);
  STRING line;
  get(f, (line, newline));
  print(("1: ", line, newline));
  get(f, (line, newline));
  print(("2: ", line, newline));
  close(f)
END

The program writes the file first so that the example is complete, then opens it for reading and takes the two lines. The text is the same as the text that was written, because get of a string keeps every character up to the newline. The final close releases the file.

$ a68g readfile.a68
1: alpha
2: beta

Every line of a file

A file of unknown length is read with the handler for the logical end of the file. The handler sets a flag, and the loop stops when the flag becomes true, which is the same pattern that the reading input article uses for stand in.

alllines.a68
BEGIN
  STRING name = "notes.txt";
  FILE f;
  open(f, name, stand out channel);
  put(f, ("alpha", newline));
  put(f, ("beta", newline));
  put(f, ("gamma", newline));
  close(f);
  open(f, name, stand in channel);
  STRING line;
  INT count := 0;
  BOOL done := FALSE;
  on logical file end(f, (REF FILE file) BOOL: done := TRUE);
  WHILE NOT done DO
    get(f, (line, newline));
    IF NOT done THEN
      count +:= 1;
      print((whole(count, 0), ": ", line, newline))
    FI
  OD;
  close(f)
END

The handler is installed on the file variable, so it applies to the reads that follow. The read that reaches the end of the file still returns, and the guard prevents the empty result from being printed. The loop numbers the three lines as it prints them, and the count is the number of lines in the file.

$ a68g alllines.a68
1: alpha
2: beta
3: gamma

Numbers in a file

A file holds characters, not values, so a program that stores numbers first turns them into text. putf with a g frame writes a number without padding, and get with an INT variable converts it back.

numbers.a68
BEGIN
  STRING name = "values.txt";
  FILE f;
  open(f, name, stand out channel);
  []INT values = (10, 20, 30, 40);
  FOR i TO UPB values DO
    putf(f, ($g(0)$, values[i]));
    put(f, (newline))
  OD;
  close(f);
  open(f, name, stand in channel);
  INT n, total := 0;
  BOOL done := FALSE;
  on logical file end(f, (REF FILE file) BOOL: done := TRUE);
  WHILE NOT done DO
    get(f, (n, newline));
    IF NOT done THEN total +:= n FI
  OD;
  close(f);
  print(("total ", whole(total, 0), newline))
END

Each number is written as its decimal digits followed by a newline, so a line of the file can be read back as an integer. The second loop converts every line into n and adds it to the total, which is 100. A number that does not fit the mode of the variable would raise a value error, which on value error can handle.

$ a68g numbers.a68
total 100

Opening for output clears the file

open with stand out channel always starts at the beginning of an empty file. Opening an existing name again therefore discards what it held, and the new content is the only content that remains.

truncate.a68
BEGIN
  STRING name = "log.txt";
  FILE f;
  open(f, name, stand out channel);
  put(f, ("first run", newline));
  close(f);
  open(f, name, stand out channel);
  put(f, ("second run", newline));
  close(f);
  open(f, name, stand in channel);
  STRING line;
  get(f, (line, newline));
  print(("the file now holds: ", line, newline));
  close(f)
END

The second write does not append to the first; it replaces it, so the file holds one line. A program that wants to keep the old content has to read the file before it opens it for output, or write to a different name. The implementation has no channel that appends to an existing file.

$ a68g truncate.a68
the file now holds: second run

A formatted report

putf writes a formatted row to a file, so a report can be built from frames just as it is on the terminal. Reading the report back as lines shows the text that the format produced.

report.a68
BEGIN
  STRING name = "report.txt";
  FILE f;
  open(f, name, stand out channel);
  []INT values = (7, 42, 1234);
  FOR i TO UPB values DO
    putf(f, ($g(-6)$, values[i]));
    putf(f, ($" square "g(-8)$, values[i] * values[i]));
    put(f, (newline))
  OD;
  close(f);
  open(f, name, stand in channel);
  STRING line;
  BOOL done := FALSE;
  on logical file end(f, (REF FILE file) BOOL: done := TRUE);
  WHILE NOT done DO
    get(f, (line, newline));
    IF NOT done THEN print(("| ", line, newline)) FI
  OD;
  close(f)
END

Each line of the report holds a number in a field of six characters and its square in a field of eight, so the columns of the file line up. The reading part prints every line with a bar in front of it, which shows that the spaces of the fields are part of the file. A report built this way can be printed or looked at with any text tool.

$ a68g report.a68
|      7 square       49
|     42 square     1764
|   1234 square  1522756

The standard files

Every program has three files open before its first statement: stand out, stand in, and stand error. print and printf write to stand out, the reading procedures take values from stand in, and the interpreter writes its diagnostics to stand error. A program may pass any of them to put, putf, get, or read, which is why the same procedures serve both the terminal and a file of the program's own.

A file value carries more than the name: the channel decides whether the file is read or written, and the position of the next character moves with every transput. That is why a file must be closed and opened again with a different channel before it can be read after it has been written.

Next steps

The reading input article covers the same reading procedures on stand in, and the formatted transput article explains the frames that putf uses. The command-line arguments article shows how a script takes a file name from its arguments, and strings explains the text that a file holds.

Source

Revised Report on the Algorithmic Language Algol 68

The Algol 68 Genie project

In this article we have opened files for writing and reading, written lines and numbers, read them back, walked every line of a file with a handler for its end, seen that opening for output clears a file, and written a formatted report. The command-line arguments article continues with the values that a script receives from its caller.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Algol 68 tutorials.