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
Filejust represents a filename and never throws;Scanneris 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 awhileloop 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)