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
- Key Concepts
- Worked Examples
- Handling Errors Gracefully
- Quick Check
- Code Completion
- Spot the Error
- Predict the Output
- Practice Exercises
- 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 filereader.hasNextLine()returnstruewhile there are more lines to readreader.nextLine()reads and returns the next line as a Stringreader.close()releases the file resource- The
try/catchhandles 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()returnsnullat end-of-file (not a boolean check)- Catches
IOException(broader thanFileNotFoundException) - 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.
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
-
Read and count – Write a program that reads integers from
numbers.txt(one per line) and prints the sum, count, and average. -
Read into ArrayList – Read all lines from
names.txtinto anArrayList<String>. Print the total number of names and the last name in the list. -
CSV parser – Read a file
products.csvwhere each line isname,price(e.g.,Keyboard,79.99). Print each product and its price. Handle lines with invalid data by skipping them.
Extension
-
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) wheretargetfirst appears, or -1 if not found. Use.contains()for matching. -
File statistics – Read a text file and report: total lines, total words, total characters, and the longest line.
Challenge
- Merge two files – Read two sorted files of integers (
sorted1.txtandsorted2.txt, one per line) and produce a third filemerged.txtcontaining all integers in sorted order. Do not load both files into memory at once – read one line at a time from each.
Connections
- Prerequisites: Exception Handling – try/catch for file errors
- Prerequisites: ArrayList – reading unknown-length files into a dynamic list
- Prerequisites: Strings –
.split(),.trim(), parsing - Related: Writing Files – the output counterpart
- Forward: File I/O in Apps – reading files in JavaFX applications