
Everything a program has worked out vanishes when it ends. Warehouse needs to remember things between runs: the levels themselves, and the best score on each. Programs keep things on the disc in files - the same kind of thing as the .PAS files you save from the editor - and Pascal's files are built so that a file of levels is simply a list of level records, on the disc.
A file type is declared as a file of some type:
var
F: file of Level;
F is not the file itself; it is the program's handle on one. Four steps turn it into a real file on the disc:
Assign(F, 'LEVELS.DAT');
Rewrite(F);
Write(F, L);
Close(F);
Assign gives the handle a file name. Names follow the disc's rules - eight characters, a dot, a three-letter type.Rewrite creates the file, empty. If a file of that name already exists, its contents are thrown away.Write(F, L) adds the record L to the end of the file.Close finishes. Always close a file you have written: Borland's manual warns that otherwise the disc's directory may not be brought up to date, and data can be lost.To read it back:
Reset(F);
while not Eof(F) do
begin
Read(F, L);
...
end;
Close(F);
Reset opens an existing file at its beginning. Read(F, L) reads the next record into L. Eof(F) - end of file - is true when there are no more.
Every record in a file of records is the same size, so Turbo can go straight to any one of them. The records are numbered from 0:
Seek(F, 2) moves to record 2 - the third.FilePos(F) says which record is next.FileSize(F) says how many there are.And you can change one record without touching the rest: Seek to it, Read it, change it, Seek back - the Read moved you on - and Write it. That is how Warehouse will update a best score.
A file of type Text holds lines of characters, like the files the editor saves. Writeln and Readln work on it when you give them the file first:
var
T: Text;
S: string[40];
...
Writeln(T, 'Push every crate');
Readln(T, S);
Text files are read from the start, a line at a time. They are the right thing for anything a person might want to read, and the wrong thing for records.
Reset of a file that does not exist stops the program:
I/O error 01, PC=00C5
Program aborted
A program that has to cope - "is there a scores file yet?" - can turn the check off around the Reset and look for itself:
{$I-}
Reset(F);
{$I+}
if IOresult = 0 then
Writeln('Found it')
else
Writeln('Not there');
With {$I-}, a failed Reset does not stop the program; IOresult then says what happened - 0 if all was well, a number if not (1 for a missing file). Turn the check back on straight afterwards with {$I+}.
A file you no longer want goes with Erase(F) (close it first). And remember that every file costs at least 2k of disc (S6).
program LevelFile;
type
Str20 = string[20];
Level = record
Name: Str20;
Best: Integer;
end;
var
F: file of Level;
L: Level;
I: Integer;
S: Str20;
begin
Assign(F, 'LEVELS.DAT');
Rewrite(F);
for I := 1 to 3 do
begin
Str(I, S);
L.Name := 'Level ' + S;
L.Best := I * 10;
Write(F, L);
end;
Close(F);
Reset(F);
Writeln(FileSize(F), ' levels');
while not Eof(F) do
begin
Read(F, L);
Writeln(L.Name, ' best ', L.Best);
end;
Close(F);
end.
Starting from
Turbo freshly started, Y, a new work file called LFILE.
What you should see
3 levels
Level 1 best 10
Level 2 best 20
Level 3 best 30
and afterwards D lists LEVELS DAT on the disc.
Seek(F, 2); just after the line that prints how many levels there are. Which levels are printed now?Write(FilePos(F), ': '); just before Read(F, L);. What numbers appear?Reset(F);, add Assign(F, 'NOSUCH.DAT');. What happens, and where does ESC take you?21.1 Write three lines of advice to a text file called NOTES.TXT, then read the file back and print it.
21.2 After writing the three levels, change level 2's best score to 15 using Seek, then print all three.
21.3 Write a program that says whether a file called SCORES.DAT exists, without stopping if it does not.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
I/O error 01 at a Reset | The file does not exist - or its name in Assign is not the one on the disc. |
| A file that was there is empty | Rewrite was used on it, which empties it. Use Reset to read. |
A Seek lands one record out | Records are numbered from 0. Record 1 is the second. |
| Changing a record wrote over the next one | Read moves on a record; Seek back before you Write. |
| The disc is filling up | Every file costs at least 2k. Erase or ERA what you do not need. |
file of T holds records of type T on the disc: Assign a name, Rewrite to create or Reset to open, Write and Read, Close. Seek, FilePos and FileSize number records from 0, so any record can be read or changed. Text files hold lines, with Writeln and Readln. A missing file is I/O error 01 - unless {$I-} is on and you check IOresult.
S22, Pointers - making new variables while the program runs, and a list that grows and shrinks: the heart of undo.