Using Text Files

Why Read From a File

A file's data persists even when the program isn't running — useful for loading configuration or data that's too large (or too changeable) to hard-code into your source. A robot might load a table of autonomous starting positions from a file instead of hardcoding them.

Opening a File

File (from java.io) represents the file itself — really just a filename/path, and building one never fails even if the file doesn't exist. Scanner (from java.util) is what actually reads from it:

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

File configFile = new File("auto_config.csv"); // just a name — this line can't fail
Scanner scan = new Scanner(configFile); // this line can throw FileNotFoundException

import java.io.*; and import java.util.*; are wildcard imports (Ch.3.3) — they pull in every class from that package (File/IOException from java.io; Scanner from java.util) instead of naming each one individually. A relative filename like "auto_config.csv" is looked up relative to wherever the program is run from, not where the source file lives.

Since opening a file can fail (wrong name, missing file), Java requires you to acknowledge that. The simplest way: add throws IOException to the method's header — if the file genuinely can't be found, the program terminates with an error instead of continuing silently. (try/catch, the alternative to throws, is Ch.12's subject — including try-with-resources, which can close the scanner automatically instead of a manual scan.close().)

public static void main(String[] args) throws IOException
{
    File configFile = new File("auto_config.csv");
    Scanner scan = new Scanner(configFile);
    // ...
    scan.close();
}

Reading Line by Line

while (scan.hasNextLine())
{
    String line = scan.nextLine();
    // process this line
}
scan.close(); // always close when done

hasNextLine() is true as long as there's another line to read — the standard loop condition for "read until the file ends."

Splitting a CSV Line

A CSV (comma-separated values) file packs several fields into one line. String's split(",") breaks a line into a String[] around the commas:

// One line of auto_config.csv: "3-Piece-Left,14.2,BlueAlliance"
String line = scan.nextLine();
String[] fields = line.split(",");
String routeName = fields[0];       // "3-Piece-Left"
double routeTime = Double.parseDouble(fields[1]); // "14.2" -> 14.2
String alliance = fields[2];        // "BlueAlliance"

Integer.parseInt/Double.parseDouble convert text into a number — Ch.9.2 covers the wrapper classes (Integer, Double) these belong to.

Reading Into an Array or ArrayList

If you know the line count in advance, an array works; otherwise, ArrayList (Ch.9.2) avoids needing to know the size up front:

ArrayList<String> configLines = new ArrayList<String>();
while (scan.hasNextLine())
{
    configLines.add(scan.nextLine());
}

Reading Into Objects

Rather than working with raw String[] rows, define a class matching the file's columns and build one object per row — the same has-a/object-per-record idea from Ch.7:

ArrayList<AutoRoute> routes = new ArrayList<AutoRoute>();
while (scan.hasNextLine())
{
    String[] fields = scan.nextLine().split(",");
    routes.add(new AutoRoute(fields[0], Double.parseDouble(fields[1]), fields[2]));
}

Common Pitfalls

  • Forgetting throws IOException (or a try/catch). Java won't compile file-reading code unless you've acknowledged that opening the file might fail.
  • Forgetting to close() the scanner. A small leak that adds up in a program that opens many files.
  • Trying to parse a header row as data. The first line of a CSV is often column names, not values — call scan.nextLine() once before the loop starts to discard it, rather than checking for it on every pass.
  • Assuming a relative filename resolves next to the source file. It resolves relative to wherever the program is actually run from, which isn't always the same folder.

Key Takeaways

  • File just represents a filename and never throws; Scanner is what can throw (FileNotFoundException) when it actually tries to open that file — Java requires you to acknowledge that (throws IOException, or try/catch).
  • hasNextLine() combined with a while loop is the standard pattern for reading an entire file, line by line.
  • String.split(",") breaks a CSV line into fields; Integer.parseInt/Double.parseDouble (Ch.9.2) convert a field's text into a number.
  • Reading rows into custom objects (one object per line) is cleaner than working with raw split arrays once the data has real structure.

Derived from csawesome-2026: unit-4-data-collections/4.06-using-text-files.md (CSA 4.6)