Python Foundations

Random Files

Fixed-length records and direct (random) access to file data — the record TYPE, OPENFILE FOR RANDOM, SEEK, GETRECORD, PUTRECORD, CLOSEFILE in pseudocode, and pickle + seek in Python. Direct access without reading every record before it.

10.1 What a Random File Is — Direct Access

There are three ways a file can be organised. Understanding the difference is essential before the code makes sense.

TypeOrderAccessExample
SerialArrival order (no sorting)Sequential — read from startReceipts in a box
SequentialSorted by key fieldSequential — read in orderPaper dictionary
RandomFixed-length recordsDirect — jump to any recordLibrary database
Key rule:
  • A random file = fixed-length records + direct access.
  • Because every record is the same size, the program can calculate exactly where record N begins.
  • It can then jump straight there using SEEK — that jump is direct access.
Exam tip:
  • A random file allows direct access — any record can be reached by its position.
  • A single book can be read or updated without reading the records before it.
  • Access is therefore much faster for a large file.
Your Turn — Serial vs Sequential [2 marks]
Explain one difference between how records are stored in a serial file and a sequential file.
Hint:
  • Both store records one after another
  • The difference is about order
  • Serial = no sorting; Sequential = sorted by key field
Your Turn — Which file organisation?
A program must reach customer record number 8,000 as fast as possible, without reading any other record. Which file organisation supports this?
Hint:
  • Direct access = jump straight to the record
  • Only one file type supports this
  • Think: which type allows SEEK?

10.2 The Record Type & The Five Commands

First you describe the shape of one record using a user-defined TYPE. This is the blueprint — it does not store data yet, it just says what fields a record has and what type each field is.

TYPE Book
    DECLARE Title : STRING
    DECLARE Author : STRING
    DECLARE YearPublished : INTEGER
    DECLARE ISBN : STRING
    DECLARE CopiesAvailable : INTEGER
ENDTYPE

Then you use the five file commands:

CommandPurpose
OPENFILE "file" FOR RANDOMOpens the file for direct access
SEEK "file", positionMoves the pointer to a record position
GETRECORD "file", variableReads the record at the pointer into a variable
PUTRECORD "file", variableWrites the variable to the pointer position
CLOSEFILE "file"Closes the file and saves changes
Key rule:
  • SEEK positions the pointer; GETRECORD reads from that slot and PUTRECORD writes into it.
  • SEEK must always come before GETRECORD or PUTRECORD.
Your Turn — Declare a record type [3 marks]
Write pseudocode to declare a composite type Member for the library, storing a membership number (integer), a name (string), and an active status (boolean).
Hint:
  • Use TYPE...ENDTYPE wrapper
  • Three DECLARE lines with correct names
  • Correct data types: INTEGER, STRING, BOOLEAN
Your Turn
Write pseudocode to declare a composite type Loan storing a loan ID (integer), a borrower name (string), and a due date (date).
Hint:
  • Same shape as Member: TYPE, three DECLARE lines, ENDTYPE
  • Pick the right type for a date

10.3 Adding a Record — PUTRECORD

Adding follows three steps: build the record in a variable, SEEK to where it should go, then PUTRECORD to write it. There is no read involved — you are writing fresh data in.

DECLARE NewBook : Book

// 1. Build the record in a variable
NewBook.Title <- "Pride and Prejudice"
NewBook.Author <- "Jane Austen"
NewBook.YearPublished <- 1813
NewBook.ISBN <- "9780141199078"
NewBook.CopiesAvailable <- 12

// 2. Open, SEEK to position, PUTRECORD
OPENFILE "LibraryDatabase.dat" FOR RANDOM
SEEK "LibraryDatabase.dat", 5
PUTRECORD "LibraryDatabase.dat", NewBook
CLOSEFILE "LibraryDatabase.dat"
Your Turn — Add a book to position 9
Write pseudocode to add a new book (variable NewBook with Title "Hamlet", Author "William Shakespeare", YearPublished 1601, ISBN "9780743477123", CopiesAvailable 5) to position 9 of LibraryDatabase.dat.
Hint:
  • Assign every field of NewBook
  • OPENFILE FOR RANDOM
  • SEEK to position 9, then PUTRECORD
  • CLOSEFILE
Your Turn — Add a member to position 4
Write pseudocode to add a new member (MembershipNo 2041, Name "Musarrat", Active TRUE) to position 4 of Members.dat.
Hint:
  • Same three steps — the variable is of type Member
  • Assign all three fields
  • SEEK to position 4, PUTRECORD, CLOSEFILE
Your Turn — Write variable to position 0
Open Members.dat FOR RANDOM and write the variable M into position 0.
Hint:
  • OPENFILE, SEEK to 0, PUTRECORD, CLOSEFILE
  • Only 4 lines needed
Your Turn
Write the variable L into position 12 of Loans.dat.
Hint:
  • Same four lines, change the file and position
Exam tip:
  • Assign every field of the record before writing it.
  • Examiners check that each field of the user-defined type is set before PUTRECORD.
  • Unassigned fields may contain garbage.

10.4 Reading & Updating a Record

The update cycle: read the slot, change a field in the variable, then write the variable back to the same slot.

DECLARE ExistingBook : Book
OPENFILE "LibraryDatabase.dat" FOR RANDOM

// read the record at position 5
SEEK "LibraryDatabase.dat", 5
GETRECORD "LibraryDatabase.dat", ExistingBook

// change one field
ExistingBook.CopiesAvailable <- 20

// write it back to the SAME slot
SEEK "LibraryDatabase.dat", 5
PUTRECORD "LibraryDatabase.dat", ExistingBook
CLOSEFILE "LibraryDatabase.dat"
Your Turn — Update CopiesAvailable at position 3
Read the book at position 3 into B, increment CopiesAvailable by 1, and write it back.
Hint:
  • SEEK 3, GETRECORD into B
  • B.CopiesAvailable = B.CopiesAvailable + 1
  • SEEK 3 again, PUTRECORD B
  • CLOSEFILE
Your Turn — Deactivate a member at position 8
Read the member at position 8 into M, set Active to FALSE, and write it back.
Hint:
  • Read, change the one field (Active)
  • SEEK back to 8, write
Your Turn — Read and output a title
Read the book at position 2 into B and output its title.
Hint:
  • No write needed — just SEEK, GETRECORD, OUTPUT
  • Output B.Title
Your Turn
Read the member at position 7 in Members.dat into M and output their name.
Hint:
  • SEEK 7, GETRECORD into M
  • OUTPUT M.Name
  • No PUTRECORD needed

10.5 Shifting Records to Make Space

To insert a record in the middle of a file, you must first shift all records after that position one slot forward. Start from the last record and work backward to avoid overwriting records you have not moved yet.

DECLARE Pupil : Student
DECLARE Position : INTEGER
OPENFILE "StudentFile.dat" FOR RANDOM

// move records from 20 down to 10, backward, into the next slot
FOR Position <- 20 TO 10 STEP -1
    SEEK "StudentFile.dat", Position
    GETRECORD "StudentFile.dat", Pupil
    SEEK "StudentFile.dat", Position + 1
    PUTRECORD "StudentFile.dat", Pupil
NEXT Position
CLOSEFILE "StudentFile.dat"
Key rule — shift backward:
  • Always shift from the last record backward (STEP -1).
  • If you shift forward, you overwrite the next record before you have read it — destroying data.
Your Turn — Shift books from 12 to 8
Write pseudocode to shift book records from position 12 down to position 8, each moving to position + 1, in LibraryDatabase.dat.
Hint:
  • Loop from 12 TO 8 STEP -1 (backward)
  • SEEK position, GETRECORD, SEEK position+1, PUTRECORD
  • Work backward to avoid overwriting
Your Turn
Write pseudocode to shift member records from position 15 down to position 5, each moving to position + 1, in Members.dat.
Hint:
  • Same pattern — loop 15 TO 5 STEP -1
  • Read from Position, write to Position + 1

10.6 Searching a Random File

To search for a record by name (or any field), loop through positions with SEEK + GETRECORD, compare each record's field, and stop when found. Use a Boolean flag.

DECLARE Customer : Member
DECLARE Position : INTEGER
DECLARE Found : BOOLEAN
DECLARE SearchName : STRING

OUTPUT "Enter the member's name"
INPUT SearchName
Found <- FALSE
Position <- 0
OPENFILE "Members.dat" FOR RANDOM

WHILE Found = FALSE AND Position < 1000 DO
    SEEK "Members.dat", Position
    GETRECORD "Members.dat", Customer
    IF Customer.Name = SearchName THEN
        Found <- TRUE
    ELSE
        Position <- Position + 1
    ENDIF
ENDWHILE
CLOSEFILE "Members.dat"

IF Found THEN
    OUTPUT "Found at position", Position
ELSE
    OUTPUT "Not found"
ENDIF
Key rule:
  • The search uses a WHILE loop with two conditions: Found = FALSE AND Position < maxRecords.
  • This stops either when the record is found or when all records have been checked.

10.7 Python — Serialising with pickle

Python does not have Cambridge pseudocode's PUTRECORD / GETRECORD. Instead, the pickle module lets you serialise any Python object (class instance, dictionary, list) to a binary file and read it back.

import pickle

class Book:
    def __init__(self, title, author, year, isbn, copies):
        self.title = title
        self.author = author
        self.year = year
        self.isbn = isbn
        self.copies = copies

    def __str__(self):
        return f"{self.title} by {self.author} ({self.copies} copies)"

book = Book("To Kill a Mockingbird", "Harper Lee", 1960,
            "9780060935467", 5)

# Write (like PUTRECORD)
with open("book.dat", "wb") as f:
    pickle.dump(book, f)

# Read back (like GETRECORD)
with open("book.dat", "rb") as f:
    loaded = pickle.load(f)

print(loaded)  # To Kill a Mockingbird by Harper Lee (5 copies)
pickle equivalence:
  • pickle.dump(obj, file) = PUTRECORD (write object).
  • pickle.load(file) = GETRECORD (read object).
  • The file mode is "wb" for writing binary, "rb" for reading binary.
Your Turn — Pickle a dictionary
Use pickle to save a dictionary member = {"id": 2041, "name": "Tarnima", "active": True} to member.dat, then read it back and print it.
Hint:
  • Import pickle
  • open("member.dat", "wb") + pickle.dump()
  • open("member.dat", "rb") + pickle.load()
  • Print the loaded dictionary
Your Turn — Pickle a list
Use pickle to save a list titles = ["Hamlet", "1984", "Matilda"] to titles.dat, then read it back and print each title.
Hint:
  • Same pattern — dump the list, load it back
  • Loop through the loaded list to print each title

10.8 Python — Direct Access with seek

To replicate Cambridge pseudocode's SEEK + fixed record size in Python, use file.seek(position * RECORD_SIZE) to jump to a record, then pickle.dump() / pickle.load() to read or write.

import pickle

RECORD_SIZE = 128  # every record reserves a fixed block

def put_record(filename, position, record):
    with open(filename, "r+b") as f:
        f.seek(position * RECORD_SIZE)  # like SEEK
        pickle.dump(record, f)           # like PUTRECORD

def get_record(filename, position):
    with open(filename, "rb") as f:
        f.seek(position * RECORD_SIZE)  # like SEEK
        return pickle.load(f)           # like GETRECORD
Key rule — byte offset:
  • The byte offset for record N is N * RECORD_SIZE.
  • For record 6 with size 200: seek(6 * 200) = seek(1200).
  • This is the Python equivalent of SEEK "file", 6.
Your Turn — Write to record 2
Given RECORD_SIZE = 128, write Python code to seek to record 2 of lib.dat and pickle.dump a Book object b.
Hint:
  • Offset = 2 * 128 = 256
  • Open in "r+b" mode (read+write binary)
  • f.seek(2 * 128) then pickle.dump(b, f)
Your Turn — Read from record 5
Given RECORD_SIZE = 128, write Python code to seek to record 5 of lib.dat and load a Book object into b.
Hint:
  • Offset = 5 * 128 = 640
  • Open in "rb" mode (read binary)
  • f.seek(5 * 128) then b = pickle.load(f)

10.9 Full Exam-Style Question

A driving school stores lesson records in a random file Lessons.dat. Each record is of type TLesson:

TYPE TLesson
    DECLARE LessonID : INTEGER
    DECLARE StudentName : STRING
    DECLARE Instructor : STRING
    DECLARE Booked : BOOLEAN
ENDTYPE
(a) — Write a record [3 marks] The variable NewLesson of type TLesson has been filled. Write pseudocode to write NewLesson to position 10 of Lessons.dat.
Your Turn — (a) Model answer
Fill in the blanks: OPENFILE Lessons.dat FOR RANDOM / SEEK Lessons.dat, ... (i) / ... Lessons.dat, NewLesson (ii) / CLOSEFILE ... (iii)
Hint:
  • (i) SEEK to position 10
  • (ii) PUTRECORD to write NewLesson
  • (iii) CLOSEFILE Lessons.dat
(b) — Search for a student [7 marks]
  • Write a pseudocode procedure FindStudent(Target : STRING) that searches Lessons.dat for a lesson where StudentName equals Target and Booked is TRUE.
  • Output the lesson ID and instructor if found, or "Not found".
  • The file has 500 records.
Your Turn — (b) Model answer
Click Show Answer to see the full FindStudent procedure.
Hint:
  • Declare Lesson, Index, Found
  • Found = FALSE, Index = 0
  • WHILE Index < 500 AND Found = FALSE
  • SEEK, GETRECORD, check StudentName AND Booked
  • If match: output and set Found = TRUE
  • Else Index = Index + 1
  • After loop: if not found, output "Not found"
(c) — Python equivalent [3 marks] Write Python code to read the record at slot Slot from Lessons.dat using RECORD_SIZE = 96 and pickle.
Your Turn — (c) Model answer
Click Show Answer to see the Python code for reading a record at a given slot.
Hint:
  • RECORD_SIZE = 96
  • Open in "rb" mode
  • f.seek(Slot * RECORD_SIZE)
  • lesson = pickle.load(f)

Key Points Summary

A random file = fixed-length records + direct access via SEEK.
Serial = no order; Sequential = sorted by key; Random = direct access.
TYPE...ENDTYPE defines a record type with DECLARE lines for each field.
Five commands: OPENFILE FOR RANDOM, SEEK, GETRECORD, PUTRECORD, CLOSEFILE.
SEEK positions the pointer; GETRECORD reads; PUTRECORD writes — SEEK always first.
Adding: build record, SEEK to position, PUTRECORD, CLOSEFILE.
Updating: SEEK, GETRECORD, change field, SEEK back, PUTRECORD.
Assign every field before PUTRECORD — examiners check this.
Shifting: loop backward (STEP -1) from last to first to avoid overwriting.
Searching: WHILE loop with SEEK+GETRECORD, Boolean flag, stop when found.
Python: pickle.dump() = PUTRECORD, pickle.load() = GETRECORD.
Python direct access: file.seek(N * RECORD_SIZE) to jump to record N.
Binary file modes: "wb" for writing, "rb" for reading, "r+b" for both.

10.10 Practice Tasks

Fifteen exam-style random file tasks. Each shows only the question — click Hint for the thought process, or Help for the worked solution.

Exam tip:
  • For every random file task, the marker checks: (1) correct OPENFILE FOR RANDOM, (2) SEEK before GETRECORD/PUTRECORD, (3) all fields assigned before PUTRECORD, (4) CLOSEFILE at the end.
  • The most common mark loss is forgetting SEEK before GETRECORD/PUTRECORD.
1Practice Task — Declare a record type [3 marks]
Write pseudocode to declare a type Product with fields: ProductID (INTEGER), Name (STRING), Price (REAL), InStock (BOOLEAN).
2Practice Task — Add a record to position 0 [3 marks]
Write pseudocode to write the variable P (of type Product) to position 0 of Products.dat.
3Practice Task — Add a record to position 15 [3 marks]
Write pseudocode to write the variable C (of type Customer) to position 15 of Customers.dat.
4Practice Task — Read and output a field [3 marks]
Write pseudocode to read the product at position 5 into P and output its Name.
5Practice Task — Update a record [4 marks]
Read the product at position 3 into P, set InStock to FALSE, and write it back.
6Practice Task — Increment a field [4 marks]
Read the product at position 7 into P, add 10 to Price, and write it back.
7Practice Task — Shift records backward [5 marks]
Write pseudocode to shift product records from position 20 down to position 10, each moving to position + 1.
8Practice Task — Search by name [6 marks]
Write a pseudocode procedure FindProduct(Target : STRING) that searches Products.dat (200 records) for a product where Name = Target. Output the ProductID if found, or "Not found".
9Practice Task — Pickle save a list [3 marks]
Use Python pickle to save the list ["red", "green", "blue"] to colors.dat, then read it back and print it.
10Practice Task — Pickle save a class object [4 marks]
Define a Python class Student with __init__(self, id, name, grade). Create an object, pickle it to student.dat, then load and print it.
11Practice Task — Python seek to record N [3 marks]
Given RECORD_SIZE = 100, write Python code to seek to record 8 and pickle.dump an object obj.
12Practice Task — Python read record N [3 marks]
Given RECORD_SIZE = 100, write Python code to seek to record 3 and load an object from data.dat.
13Practice Task — Serial vs Sequential vs Random [3 marks]
State one difference between serial, sequential and random file organisation.
14Practice Task — Update with Python seek [5 marks]
Write a Python function update_record(filename, position, RECORD_SIZE) that reads a record at position, calls a callback to modify it, and writes it back. Use pickle.
15Practice Task — Why w mode is wrong for reading [2 marks]
A student opens a random file with OPENFILE "data.dat" FOR WRITE to read a record. Explain why this is incorrect.

Question Bank

Answer all questions, then press Submit Quiz to see your score.

0/12 answered

Question 1Multiple Choice

What is the key feature of a random file?

Question 2True / False

In a random file, you must read records 0-7999 before reading record 8000.

Question 3Multiple Choice

Which pseudocode keyword defines a record type?

Question 4Multiple Choice

Which command positions the file pointer at a specific record?

Question 5True / False

PUTRECORD replaces whatever was previously at the target position.

Question 6Multiple Choice

What are the steps to update a record?

Question 7Multiple Choice

In Python, which module serialises objects to a binary file?

Question 8True / False

In Python, file.seek(N * RECORD_SIZE) positions the pointer at record N.

Question 9Multiple Choice

When shifting records to make space, you should start from:

Question 10Multiple Choice

Which is the correct pseudocode to read the record at position 3?

Question 11True / False

A serial file stores records in the order they arrive, with no sorting.

Question 12Multiple Choice

What file mode is used to open a random file in Cambridge pseudocode?

Answer all 12 questions to enable submission.