Reading Files

IB Syllabus: B2.5.1 – Construct code to perform file-processing operations: open files in read mode, read from files, close files.


Key Concepts

Why Read from Files?

Every program you have written so far gets input from the keyboard and loses all data when it ends. Files let your program:

  • Load data saved by a previous run (e.g., high scores, student records)
  • Process large datasets that would be impractical to type each time
  • Read configuration or settings

Reading with Scanner

The Scanner class you already know for keyboard input also reads files. The only difference is what you pass to its constructor. (Python has no Scanner: open() gives you a file object, and its readline() method reads one line at a time.)

import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;

public class ReadFile {
    public static void main(String[] args) {
        try {
            Scanner reader = new Scanner(new File("scores.txt"));

            while (reader.hasNextLine()) {
                String line = reader.nextLine();
                System.out.println(line);
            }

            reader.close();

        } catch (FileNotFoundException e) {
            System.out.println("Error: file not found.");
        }
    }
}
try:
    f = open("scores.txt", "r")

    line = f.readline()
    while line != "":                   # readline() returns "" at end of file
        print(line.rstrip("\n"))        # readline() keeps the newline - remove it so the output matches
        line = f.readline()

    f.close()

except FileNotFoundError:
    print("Error: file not found.")

Key points:

  • new File("scores.txt") creates a File object pointing to the file
  • reader.hasNextLine() returns true while there are more lines to read
  • reader.nextLine() reads and returns the next line as a String
  • reader.close() releases the file resource
  • The try/catch handles the case where the file does not exist

Always close the file when done. Failing to close leaves the file handle open, which can cause problems if other code tries to access it.

Reading and Parsing Data

Most files contain structured data that needs to be parsed (split into meaningful parts).

File: students.csv

Alice,85
Bob,72
Charlie,91
try {
    Scanner reader = new Scanner(new File("students.csv"));
    int total = 0;
    int count = 0;

    while (reader.hasNextLine()) {
        String line = reader.nextLine();
        String[] parts = line.split(",");

        String name = parts[0];
        int score = Integer.parseInt(parts[1].trim());

        System.out.println(name + " scored " + score);
        total += score;
        count++;
    }

    reader.close();

    if (count > 0) {
        System.out.println("Average: " + (double) total / count);
    }

} catch (FileNotFoundException e) {
    System.out.println("File not found.");
}
try:
    f = open("students.csv", "r")
    total = 0
    count = 0

    line = f.readline()
    while line != "":
        parts = line.split(",")

        name = parts[0]
        score = int(parts[1].strip())    # strip() also removes the newline readline() keeps

        print(name, "scored", score)
        total = total + score
        count = count + 1

        line = f.readline()

    f.close()

    if count > 0:
        print("Average:", total / count)    # / always gives a decimal in Python - no cast needed

except FileNotFoundError:
    print("File not found.")

Output:

Alice scored 85
Bob scored 72
Charlie scored 91
Average: 82.66666666666667

Reading with BufferedReader

BufferedReader is more efficient for large files because it reads data in chunks (a buffer) rather than character by character.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

try {
    BufferedReader reader = new BufferedReader(new FileReader("scores.txt"));

    String line = reader.readLine();
    while (line != null) {
        System.out.println(line);
        line = reader.readLine();
    }

    reader.close();

} catch (IOException e) {
    System.out.println("Error reading file: " + e.getMessage());
}
# Python has no separate BufferedReader - open() already buffers for you.
# The loop shape is the same: a priming read, then read again at the end of the body.
# One difference: readline() returns "" (an empty string) at end of file, not None.
try:
    f = open("scores.txt", "r")

    line = f.readline()
    while line != "":
        print(line.rstrip("\n"))    # readline() keeps the newline - remove it so the output matches
        line = f.readline()

    f.close()

except FileNotFoundError:
    print("Error reading file.")

Key differences from Scanner:

  • readLine() returns null at end-of-file (not a boolean check)
  • Catches IOException (broader than FileNotFoundException)
  • More efficient for large files
Class Best For End-of-File Signal
Scanner(File) Small files, mixed types hasNextLine() returns false
BufferedReader Large files, line-by-line readLine() returns null

try-with-resources

Java’s try-with-resources syntax automatically closes the file, even if an exception occurs:

try (Scanner reader = new Scanner(new File("data.txt"))) {
    while (reader.hasNextLine()) {
        System.out.println(reader.nextLine());
    }
}  // reader is automatically closed here

This is cleaner than manually calling close() in a finally block. (Python has a similar shortcut, the with statement, but IB Python uses explicit open() and close() - so we do too.)


Worked Examples

Example 1: Count Lines in a File

public static int countLines(String filename) throws FileNotFoundException {
    Scanner reader = new Scanner(new File(filename));
    int count = 0;
    while (reader.hasNextLine()) {
        reader.nextLine();
        count++;
    }
    reader.close();
    return count;
}
def count_lines(filename):
    f = open(filename, "r")
    count = 0
    line = f.readline()
    while line != "":
        count = count + 1
        line = f.readline()
    f.close()
    return count

Example 2: Find Maximum Value

Read a file of integers (one per line) and find the largest.

public static int findMax(String filename) throws FileNotFoundException {
    Scanner reader = new Scanner(new File(filename));
    int max = Integer.MIN_VALUE;

    while (reader.hasNextLine()) {
        int value = Integer.parseInt(reader.nextLine().trim());
        if (value > max) {
            max = value;
        }
    }

    reader.close();
    return max;
}
def find_max(filename):
    f = open(filename, "r")
    largest = None    # Python ints have no MIN_VALUE - None means "nothing seen yet"
                      # (named largest, not max, because max() is a built-in function)
    line = f.readline()
    while line != "":
        value = int(line.strip())
        if largest == None or value > largest:
            largest = value
        line = f.readline()

    f.close()
    return largest

Example 3: Read into an ArrayList

When you do not know how many lines a file has, read into an ArrayList.

public static ArrayList<String> readAllLines(String filename) throws FileNotFoundException {
    ArrayList<String> lines = new ArrayList<>();
    Scanner reader = new Scanner(new File(filename));

    while (reader.hasNextLine()) {
        lines.add(reader.nextLine());
    }

    reader.close();
    return lines;
}
def read_all_lines(filename):
    lines = []    # a plain Python list grows as needed - no ArrayList required
    f = open(filename, "r")

    line = f.readline()
    while line != "":
        lines.append(line.rstrip("\n"))    # store the line without its newline, like nextLine() does
        line = f.readline()

    f.close()
    return lines

Handling Errors Gracefully

File Not Found

File file = new File("data.txt");
if (!file.exists()) {
    System.out.println("File does not exist. Starting with empty data.");
    return new ArrayList<>();
}
// ... proceed to read
# Python has no File object - check by trying to open the file.
# (Shown inside a function, like the Java version, so return works.)
def load_data():
    try:
        f = open("data.txt", "r")
    except FileNotFoundError:
        print("File does not exist. Starting with empty data.")
        return []
    # ... proceed to read

Corrupt Data

Skip lines that cannot be parsed instead of crashing:

while (reader.hasNextLine()) {
    String line = reader.nextLine();
    try {
        String[] parts = line.split(",");
        String name = parts[0].trim();
        int score = Integer.parseInt(parts[1].trim());
        students.add(new Student(name, score));
    } catch (NumberFormatException e) {
        System.out.println("Skipping invalid line: " + line);
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Skipping malformed line: " + line);
    }
}
line = f.readline()
while line != "":
    try:
        parts = line.split(",")
        name = parts[0].strip()
        score = int(parts[1].strip())
        students.append(Student(name, score))
    except ValueError:      # int() failed - the score was not a number
        print("Skipping invalid line:", line.rstrip("\n"))
    except IndexError:      # no comma on the line, so parts[1] does not exist
        print("Skipping malformed line:", line.rstrip("\n"))
    line = f.readline()

Quick Check

Q1. What does reader.hasNextLine() return at the end of a file?

Q2. How does BufferedReader signal the end of a file?

Q3. How do you extract the name and score from the CSV line "Alice,85"?

Q4. What exception is thrown when you try to read a file that does not exist?

Q5. Why is it important to call reader.close() after reading a file?


Code Completion

Complete the method that reads a file and returns the sum of all integers.

Fill in the blanks: Read integers from a file, one per line.

public static int sumFromFile(String filename) throws FileNotFoundException {
    Scanner reader = new Scanner(new (filename));
    int total = 0;
    while (reader.) {
        total += Integer.parseInt(reader..trim());
    }
    reader.;
    return total;
}

Spot the Error

This code should read all lines but it only reads every other line.

Bug Hunt: This code should print every line, but it skips every other line.

1Scanner reader = new Scanner(new File("data.txt")); 2while (reader.hasNextLine()) { 3 reader.nextLine(); // reads a line (discarded) 4 System.out.println(reader.nextLine()); // reads ANOTHER line 5}

Pick the correct fix:


Predict the Output

Predict: Given the file students.csv containing Alice,85 / Bob,72 / Charlie,91, what are the first three lines of output?

Scanner reader = new Scanner(new File("students.csv"));
while (reader.hasNextLine()) {
    String[] parts = reader.nextLine().split(",");
    System.out.println(parts[0]);
}
reader.close();

Practice Exercises

Core

  1. Read and count – Write a program that reads integers from numbers.txt (one per line) and prints the sum, count, and average.

  2. Read into ArrayList – Read all lines from names.txt into an ArrayList<String>. Print the total number of names and the last name in the list.

  3. CSV parser – Read a file products.csv where each line is name,price (e.g., Keyboard,79.99). Print each product and its price. Handle lines with invalid data by skipping them.

Extension

  1. Search a file – Write a method findInFile(String filename, String target) that reads a file line by line and returns the line number (1-based) where target first appears, or -1 if not found. Use .contains() for matching.

  2. File statistics – Read a text file and report: total lines, total words, total characters, and the longest line.

Challenge

  1. Merge two files – Read two sorted files of integers (sorted1.txt and sorted2.txt, one per line) and produce a third file merged.txt containing all integers in sorted order. Do not load both files into memory at once – read one line at a time from each.

Connections


© EduCS.me — A resource hub for Computer Science education

This site uses Just the Docs, a documentation theme for Jekyll.