Tutorial 11

💾

Files

0984 IGCSE


In this tutorial, we'll look at how to both read from and write to files

It is important to remember that when we open a file using OPENFILE, we must close it with a corresponding CLOSEFILE later in the program - this is so the file lock can be removed and it can be modified by another process (you don't want two processes writing to the same file at the same time, since that could cause data corruption/inconsistency)

Note: there are some example files at the bottom of the page you can use to test your programs

1

File Modes

For IG, there are only two file modes - READ and WRITE

  • READ: opens a file that already exists to be read
  • WRITE: creates a new file/overwrites an existing file to write to

The following example shows us opening and closing a file in these modes - we aren't actually reading or writing any data here

Note: as shown below, file names can be either in or out of quotes

OPENFILE Jokes.txt FOR READ OPENFILE "MovieQuotes.txt" FOR WRITE CLOSEFILE "Jokes.txt" CLOSEFILE MovieQuotes.txt

We can also use a constant or variable to store filenames:

CONSTANT scores ← "scores.txt" DECLARE students : STRING students ← "students.txt" OPENFILE scores FOR READ OPENFILE students FOR WRITE CLOSEFILE scores CLOSEFILE students

2

Writing to a File

We can use WRITEFILE followed by the file and data to write

OPENFILE palindromes.txt FOR WRITE WRITEFILE palindromes.txt, "Was it a car or a cat I saw" WRITEFILE palindromes.txt, "Mr. Owl ate my metal worm." WRITEFILE palindromes.txt, "Yo, Banana Boy!" CLOSEFILE palindromes.txt

3

Reading from a File

For IGCSE/O-Level, there is no way to determine the number of lines in a file/when we reach the end of the file - hence if you ever have to read a file, we should be told the number of lines the file contains

As an example, reading from the palindrome file we just created, we can simply read 3 lines from the file by doing this:

READFILE is followed by the file we are reading from, then a variable where we will store the line we just read - here, I simply called it "line"

DECLARE lineNum : INTEGER DECLARE line : STRING lineNum ← 0 OPENFILE palindromes.txt FOR READ FOR lineNum ← 1 TO 3 READFILE palindromes.txt, line OUTPUT "Palindrome ", lineNum, ": ", line NEXT lineNum CLOSEFILE palindromes.txt

If this is a bit confusing, here is equivalent code outside a loop - of course a loop is more flexible/convenient especially for files with huge or unknown numbers of lines (AS)

DECLARE lineNum : INTEGER DECLARE line : STRING lineNum ← 0 OPENFILE palindromes.txt FOR READ READFILE palindromes.txt, line OUTPUT "Palindrome 1: ", line READFILE palindromes.txt, line OUTPUT "Palindrome 2: ", line READFILE palindromes.txt, line OUTPUT "Palindrome 3: ", line CLOSEFILE palindromes.txt

4

Technology Quotes

Create a program to output a numbered list of all the 59 technology quotes in the following numbered format, with each quote having an empty line between them

DECLARE lineNum : INTEGER DECLARE quote : STRING lineNum ← 0 OPENFILE TechnologyQuotes.txt FOR READ FOR lineNum ← 1 TO 59 READFILE TechnologyQuotes.txt, quote OUTPUT lineNum, ") ", quote OUTPUT "" NEXT lineNum CLOSEFILE TechnologyQuotes.txt

5

Student Scores

Use the 12 student names and 12 scores to create a program that outputs the data in the following format: "Albert scored 62"

Note: the student names/scores are in the same order in both files - i.e. line 1 refers to student 1's score, line 2 to student 2's score etc

Extension: you could use the AS STR_TO_NUM function to convert the scores into integers - which you could then find the min/max score/student, the average, the number who passed/failed (with e.g. 50% being the passing score)

DECLARE lineNum : INTEGER DECLARE studentName, studentScore : STRING lineNum ← 0 OPENFILE students.txt FOR READ OPENFILE scores.txt FOR READ FOR lineNum ← 1 TO 12 READFILE students.txt, studentName READFILE scores.txt, studentScore OUTPUT studentName, " scored ", studentScore NEXT lineNum CLOSEFILE students.txt CLOSEFILE scores.txt

6

Movie Quotes from Decade

Use the 20 movie quotes to create a program that allows people to input a decade, then outputs all the movie quotes from that decade along with the count

If no movie quotes exist for that decade, a message notifying the user of this should be displayed

The program should continue until the user enters nothing for the decade

CONSTANT MOVIE_FILE ← "MovieQuotes.txt" DECLARE chosenDecade, quote : STRING DECLARE quoteNum, quoteCount : INTEGER REPEAT OUTPUT "Choose decade:" INPUT chosenDecade IF chosenDecade <> "" THEN OUTPUT "--- Quotes from ", chosenDecade, "s ---" chosenDecade ← SUBSTRING(chosenDecade, 1, 3) //e.g. "1960" becomes "196" OPENFILE MOVIE_FILE FOR READ quoteCount ← 0 FOR quoteNum ← 1 TO 20 READFILE MOVIE_FILE, quote IF SUBSTRING(quote, LENGTH(quote) - 4, 3) = chosenDecade THEN OUTPUT quote quoteCount ← quoteCount + 1 ENDIF NEXT quoteNum CLOSEFILE MOVIE_FILE IF quoteCount > 0 THEN OUTPUT "--- Found ", quoteCount, " Quotes ---" ELSE OUTPUT "--- No Quotes Found ---" ENDIF ENDIF UNTIL chosenDecade = ""

7

Remove Blank Lines

Note how the technology facts is poorly formatted with many blank lines - create a program that will copy all of the facts and exclude the empty lines to a new text file

A count of the number of lines written and number of empty lines removed should also be displayed

CONSTANT OLD_FILE ← "facts.txt" CONSTANT NEW_FILE ← "facts-new.txt" DECLARE line : STRING DECLARE factCount, emptyLineCount, lineNum : INTEGER factCount ← 0 emptyLineCount ← 0 OPENFILE OLD_FILE FOR READ OPENFILE NEW_FILE FOR WRITE FOR lineNum ← 1 TO 98 READFILE OLD_FILE, line IF line <> "" THEN WRITEFILE NEW_FILE, line factCount ← factCount + 1 ELSE emptyLineCount ← emptyLineCount + 1 ENDIF NEXT lineNum CLOSEFILE OLD_FILE CLOSEFILE NEW_FILE OUTPUT factCount, " facts written and ", emptyLineCount, " empty lines removed"

8

Random Joke

Create a program that reads all 12 jokes into a 2D array, with the 1st column containing the question and the 2nd column containing the answer/joke (note: if the joke consists of just a single line, then the 2nd line in the file has been left blank)

The user should then be continually asked how many jokes they want to hear - entering 0 or less should result in the program terminating

DECLARE jokes : ARRAY[1:12, 1:2] OF STRING DECLARE jokeNum, jokeAmount, randIndex : INTEGER DECLARE line : STRING OPENFILE Jokes.txt FOR READ FOR jokeNum ← 1 TO 12 READFILE Jokes.txt, jokes[jokeNum, 1] READFILE Jokes.txt, jokes[jokeNum, 2] READFILE Jokes.txt, line NEXT jokeNum CLOSEFILE Jokes.txt REPEAT OUTPUT "How many jokes would you like to hear?" INPUT jokeAmount FOR jokeNum ← 1 TO jokeAmount randIndex ← 1 + ROUND(RANDOM() * 11, 0) OUTPUT jokes[randIndex, 1] IF jokes[randIndex, 2] <> "" THEN OUTPUT jokes[randIndex, 2] ENDIF OUTPUT "---" NEXT jokeNum UNTIL jokeAmount <= 0 OUTPUT "Goodbye..."

The following are some example files you can use throughout these challenges - you may also want to use a list of English words to try some interesting tasks too