10.3.2 Reading Multi-line Text Files
A text file may contain no lines, one line or many lines. A program normally reads one complete line at a time into a string variable. To process the whole file safely, it checks whether the end has been reached before attempting the next read.
By the end of this section, you should be able to:
- Open an existing text file in
READmode. - Use
READFILEto place one line into a string variable. - Explain how the current read position advances through a file.
- Interpret the Boolean result returned by
EOF(). - Use
WHILE NOT EOF(filename)to process every line safely. - Trace the behaviour of a reading loop for multi-line, single-line and empty files.
- Adapt the basic loop to count, search for or temporarily store file lines.
Reading One Line
Consider a delivery-status file containing one update per line:
Van 14 | loading
Bike 08 | departed
Locker 21 | delayed
Drone 03 | inspection
The file must be opened for reading before READFILE is used.
One call to READFILE copies the next unread line into a variable.
DECLARE CurrentLine : STRING
OPENFILE "DispatchNotes.txt" FOR READ
READFILE "DispatchNotes.txt", CurrentLine
OUTPUT CurrentLine
CLOSEFILE "DispatchNotes.txt"
This code outputs only the first line:
"Van 14 | loading".
| Statement | Purpose |
|---|---|
OPENFILE "DispatchNotes.txt" FOR READ |
Opens the existing file so its contents can be read. |
READFILE "DispatchNotes.txt", CurrentLine |
Copies the next unread line into CurrentLine. |
CLOSEFILE "DispatchNotes.txt" |
Finishes access to the file. |
READFILE statement does not read
an entire multi-line file. It reads only the next line.
The Current Read Position
An open file has a conceptual read position. When the file is first opened, the position
is before the first line. Each successful READFILE operation advances it to
the following line.
| After... | Value copied into CurrentLine |
Next unread line |
|---|---|---|
| Opening the file | None | Line 1 |
First READFILE |
"Van 14 | loading" |
Line 2 |
Second READFILE |
"Bike 08 | departed" |
Line 3 |
Fourth READFILE |
"Drone 03 | inspection" |
No unread lines remain |
Testing for End of File
A program cannot safely keep calling READFILE forever. It needs a way to
detect that no unread lines remain.
| File state | EOF(filename) |
NOT EOF(filename) |
|---|---|---|
| At least one unread line remains | FALSE |
TRUE |
| No unread lines remain | TRUE |
FALSE |
EOF() is not TRUE while there is
data available. It becomes TRUE when the reading position has reached the end.
WHILE NOT EOF(filename) as:
βwhile the file has not finishedβ.
Reading Every Line
A pre-condition loop checks for unread data before each call to READFILE.
The basic whole-file pattern is:
DECLARE CurrentLine : STRING
OPENFILE "DispatchNotes.txt" FOR READ
WHILE NOT EOF("DispatchNotes.txt") DO
READFILE "DispatchNotes.txt", CurrentLine
OUTPUT CurrentLine
ENDWHILE
CLOSEFILE "DispatchNotes.txt"
Structure of the algorithm
| Stage | What happens |
|---|---|
| Open | The file is opened once in READ mode. |
| Test | EOF() checks whether another line is available. |
| Read | The next line is copied into CurrentLine. |
| Process | The program uses the line; here it outputs it. |
| Repeat | The loop returns to the EOF test. |
| Close | The file is closed once no unread lines remain. |
READFILE inside the loop. Otherwise the program may repeatedly process
the same stored value without advancing through the file.
Worked Trace: Four-line File
The following trace shows the loop reading DispatchNotes.txt.
| Loop test | EOF() |
Line read | CurrentLine |
Action |
|---|---|---|---|---|
| 1 | FALSE | 1 | "Van 14 | loading" |
Output line 1 |
| 2 | FALSE | 2 | "Bike 08 | departed" |
Output line 2 |
| 3 | FALSE | 3 | "Locker 21 | delayed" |
Output line 3 |
| 4 | FALSE | 4 | "Drone 03 | inspection" |
Output line 4 |
| 5 | TRUE | None | Unchanged | Leave the loop |
READFILE after the loop. The loop has already consumed
every available line.
Why a WHILE Loop Handles an Empty File Safely
An empty file contains no data lines. Immediately after it is opened,
EOF(filename) is TRUE.
OPENFILE "NoUpdates.txt" FOR READ
WHILE NOT EOF("NoUpdates.txt") DO
READFILE "NoUpdates.txt", CurrentLine
OUTPUT CurrentLine
ENDWHILE
CLOSEFILE "NoUpdates.txt"
Because NOT EOF("NoUpdates.txt") is FALSE at the first test, the loop body
does not execute. No invalid read is attempted.
| File | Initial EOF() |
Loop-body executions |
|---|---|---|
| Empty file | TRUE | 0 |
| One-line file | FALSE | 1 |
| Four-line file | FALSE | 4 |
Processing Each Line
Output is only one possible action. The statement after READFILE can count
lines, compare the current line with a target, or perform another suitable operation.
Count the number of lines
DECLARE CurrentLine : STRING
DECLARE LineCount : INTEGER
LineCount β 0
OPENFILE "DispatchNotes.txt" FOR READ
WHILE NOT EOF("DispatchNotes.txt") DO
READFILE "DispatchNotes.txt", CurrentLine
LineCount β LineCount + 1
ENDWHILE
CLOSEFILE "DispatchNotes.txt"
OUTPUT LineCount
Find the first exact matching line
DECLARE CurrentLine : STRING
DECLARE WantedLine : STRING
DECLARE Found : BOOLEAN
WantedLine β "Locker 21 | delayed"
Found β FALSE
OPENFILE "DispatchNotes.txt" FOR READ
WHILE NOT EOF("DispatchNotes.txt") AND Found = FALSE DO
READFILE "DispatchNotes.txt", CurrentLine
IF CurrentLine = WantedLine
THEN
Found β TRUE
ENDIF
ENDWHILE
CLOSEFILE "DispatchNotes.txt"
IF Found = TRUE
THEN
OUTPUT "Matching line found"
ELSE
OUTPUT "Matching line not found"
ENDIF
Loading File Lines into an Array
A program may read persistent file data into an array so it can process the values during the current run. The array must have enough space for the lines being loaded.
DECLARE Notice : ARRAY[1:20] OF STRING
DECLARE Index : INTEGER
DECLARE LinesLoaded : INTEGER
Index β 1
OPENFILE "Notices.txt" FOR READ
WHILE NOT EOF("Notices.txt") AND Index <= 20 DO
READFILE "Notices.txt", Notice[Index]
Index β Index + 1
ENDWHILE
CLOSEFILE "Notices.txt"
LinesLoaded β Index - 1
| Condition | Why it is needed |
|---|---|
NOT EOF("Notices.txt") |
Stops when the file has no unread lines. |
Index <= 20 |
Stops before the array's upper bound is exceeded. |
Interactive: Multi-line File Reader
Choose a multi-line, single-line or empty file. Step through the EOF test, read and processing stages while the widget tracks the read position and current string value.
Common Mistakes and Misconceptions
- Opening the file in
WRITEorAPPENDmode when it should be read. - Assuming one
READFILEstatement reads every line. - Using
WHILE EOF(filename)instead ofWHILE NOT EOF(filename). - Calling
READFILEafterEOF()has become TRUE. - Placing
READFILEoutside the loop and repeatedly processing the same variable value. - Forgetting that each read replaces the previous value stored in the string variable.
- Leaving the file open after a whole-file loop or an early search result.
- Assuming an empty file will execute the loop once.
- Loading lines into an array without checking the array's upper bound.
Practice
Task 1: Read and output every line
Write pseudocode that opens "RouteAlerts.txt", outputs every line and
then closes the file.
Task 2: Trace the loop
Lab 2 | open
Studio 4 | booked
Workshop 1 | closed
- List the successive values assigned to
CurrentLine. - How many times is
READFILEexecuted? - How many times is the EOF condition tested?
- What is the value of
EOF()at the final test?
Task 3: Count lines
Adapt a whole-file reading loop so that it outputs the number of lines in
"Bookings.txt". Use an integer called BookingCount.
Task 4: Find the errors
OPENFILE "Messages.txt" FOR READ
READFILE "Messages.txt", Message
WHILE EOF("Messages.txt") DO
OUTPUT Message
ENDWHILE
- Identify at least three problems.
- Rewrite the complete algorithm correctly.
Task 5: Load an array safely
TaskName is declared as ARRAY[3:14] OF STRING.
Write pseudocode that reads as many lines as possible from
"Tasks.txt" without exceeding the array bounds.
Review
| Question | Strong answer should include |
|---|---|
What does READFILE do? |
It copies the next unread line into a variable and advances the read position. |
What does EOF() return while unread data remain? |
FALSE. |
Why use WHILE NOT EOF()? |
It checks that another line exists before attempting each read. |
| How does an empty file behave? | The first EOF test is TRUE, so the loop body executes zero times. |
| Where should the file be closed? | After the loop, or after any early termination from processing. |
| What extra condition is needed when loading a fixed-size array? | A check that the next index is not above the array's upper bound. |
READ, test NOT EOF(), read one line, process it,
repeat, then close the file.