CSCD210

Why file I/O

Skillcscd210-why-file-ioTextbookBJP Ch 6

> Canonical lecture: sources/14-w26-lectures/week-07/week7-lec1-file-io-essentials.tex §"Motivation: data lives on disk."

Up until week 7, every program reads from System.in (the keyboard) and writes to System.out (the console). That works for tiny inputs but breaks the moment the data set grows: nobody is going to retype Hamlet for a word-counting program, and nobody wants their grade report to disappear when the JVM exits. File I/O moves data between RAM (volatile, fast, gone when the program ends) and disk (non-volatile, slower, persists).

Two motivations drive everything in file input and output: input that is too large to type, and output that needs to outlive the process. Each motivates a separate Java class: Scanner on a File for input, PrintStream on a File for output. Both throw FileNotFoundException, which is why the exception machinery shows up in the same week.

Input too large to type

Student can explain why a program that processes a large data set must read from a file rather than the keyboard, and identify which constructor argument changes when switching Scanner from console to file input.

Reading from System.in works for half a dozen numbers; it falls apart for any real data set. BJP's running example is hamlet.txt: 31,956 words. No human is going to type those at a console prompt. File input changes the source from a person typing to a file already sitting on disk: new Scanner(new File("hamlet.txt")) instead of new Scanner(System.in).

The Scanner is the same class in both cases: it is the constructor argument that changes. That single design decision means everything you learned about nextInt, nextDouble, next, nextLine, hasNext in the keyboard-input chapter (BJP §3.3) carries straight over to files. The file just plays the role the keyboard used to play: a 1D character sequence the Scanner walks left-to-right.

import java.io.*;
import java.util.*;

public class CountWords {
    public static void main(final String[] args) throws FileNotFoundException {
        final Scanner input = new Scanner(new File("hamlet.txt"));
        int count = 0;
        while (input.hasNext()) {
            input.next();
            count++;
        }
        System.out.println("total words = " + count);
    }
}

In other languages

  • Python: open("hamlet.txt") returns a file object you iterate; no Scanner abstraction needed.
  • C: fopen("hamlet.txt", "r") returns a FILE*; you read with fscanf or fgets.

Output needs persistence

Student can explain why some output must be written to a file rather than the console, and identify the parallel between Scanner-on-file and PrintStream-on-file as wrappers over the same underlying data flow.

System.out.println writes to a console window. The moment the window closes (or the JVM exits), the text is gone. That is fine for debugging messages but useless for output anyone else needs to look at later: a grade report, a generated CSV, a log file. Persistence means the output survives the program's lifetime, and disk files are the standard mechanism Java offers.

The complement to "Scanner on a file" is PrintStream on a file. Just as a Scanner can wrap any input source, PrintStream can wrap any output destination. System.out itself is a PrintStream aimed at the console; constructing new PrintStream(new File("results.txt")) aims one at a file instead. Every print/println/printf call you already know works identically: only the destination differs.

import java.io.*;

public class WriteReport {
    public static void main(final String[] args) throws FileNotFoundException {
        final PrintStream output = new PrintStream(new File("results.txt"));
        output.println("Alice: 95");
        output.println("Bob: 87");
        output.close();
    }
}

After this runs, results.txt exists on disk with two lines and can be opened a week later, mailed to someone else, or fed into another program.

In other languages

  • Python: open("results.txt", "w") returns a writable file object; print(..., file=f) redirects output.
  • C: fopen("results.txt", "w") returns a FILE*; write with fprintf.