Reading Files

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

Table of Contents

  1. Key Concepts
    1. Why Read from Files?
    2. Reading with Scanner
    3. Reading and Parsing Data
    4. Reading with BufferedReader
    5. try-with-resources
  2. Worked Examples
    1. Example 1: Count Lines in a File
    2. Example 2: Find Maximum Value
    3. Example 3: Read into an ArrayList
  3. Handling Errors Gracefully
    1. File Not Found
    2. Corrupt Data
  4. Quick Check
  5. Code Completion
  6. Spot the Error
  7. Predict the Output
  8. Practice Exercises
    1. Core
    2. Extension
    3. Challenge
  9. Connections

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.

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.");
        }
    }
}

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.");
}

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());
}

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.


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;
}

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;
}

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;
}

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

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);
    }
}

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 IB Computer Science

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