File and Scanner I/O Cheat Sheet (new for 2026)
What You Need to Know
File + Scanner I/O in Java is about reading data (text) either from the keyboard (System.in) or from a text file (File) using the Scanner class. For AP CSA-style questions, the core skill is: open the input source correctly, choose the right Scanner methods (token vs line), loop until input ends, parse safely, and close resources.
The core rule
A Scanner reads input in one of two common ways:
- Token-based:
next(),nextInt(),nextDouble(), … (splits on whitespace by default) - Line-based:
nextLine()(reads the rest of the current line, including spaces)
Critical reminder:
Scannerdoes not automatically “rewind” andnextLine()behaves differently afternextInt()/next()because of leftover newline characters.
Why this matters (AP CSA 2026 angle)
If file I/O is included, you’ll likely be asked to:
- Read structured text (one item per line, or space-separated tokens)
- Compute totals/averages, count items meeting a condition, find min/max
- Build arrays/ArrayLists from file data
- Parse mixed data types in a predictable format
You need to be fluent with:
- Constructing
ScannerwithSystem.invsFile - Using
hasNext...()properly - Handling
FileNotFoundException(checked exception) - Avoiding the
nextInt()thennextLine()trap
Step-by-Step Breakdown
A. Reading from a file with Scanner (standard pattern)
Import what you need
import java.util.Scanner;import java.io.File;import java.io.FileNotFoundException;
Create the
Fileobject- Use a relative path (common in classes) or an absolute path.
Construct the
Scannernew Scanner(file)can throwFileNotFoundException.
Loop to read
- If reading tokens:
while (in.hasNext()) { ... } - If reading lines:
while (in.hasNextLine()) { ... }
- If reading tokens:
Parse and process
- Convert to numbers if needed:
Integer.parseInt(str), or read withnextInt().
- Convert to numbers if needed:
Close the scanner
in.close()or use try-with-resources.
Worked template: line-by-line
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class ReadLines {
public static void main(String[] args) throws FileNotFoundException {
File f = new File("data.txt");
Scanner in = new Scanner(f);
while (in.hasNextLine()) {
String line = in.nextLine();
// process line
System.out.println(line);
}
in.close();
}
}
Worked template: token-by-token (e.g., integers)
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class ReadInts {
public static void main(String[] args) throws FileNotFoundException {
Scanner in = new Scanner(new File("nums.txt"));
int sum = 0;
while (in.hasNextInt()) {
sum += in.nextInt();
}
in.close();
System.out.println(sum);
}
}
B. Reading from keyboard (System.in) with Scanner
Scanner kb = new Scanner(System.in);- Prompt the user (if required).
- Read using
nextLine()(strings) ornextInt()(numbers). - Deal with the newline issue if mixing methods.
Keyboard template:
import java.util.Scanner;
public class ConsoleInput {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
System.out.print("Enter age: ");
int age = kb.nextInt();
kb.nextLine(); // consume leftover newline
System.out.print("Enter name: ");
String name = kb.nextLine();
System.out.println(name + " is " + age);
kb.close();
}
}
C. Try-with-resources (cleanest for files)
Try-with-resources closes automatically:
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class SafeRead {
public static void main(String[] args) throws FileNotFoundException {
try (Scanner in = new Scanner(new File("data.txt"))) {
while (in.hasNextLine()) {
System.out.println(in.nextLine());
}
}
}
}
Decision points (what loop + method do you use?)
- File is “one record per line” (names with spaces, sentences, full CSV rows) → use
hasNextLine()+nextLine(). - File is whitespace-separated tokens (ints, words) → use
hasNextInt()/hasNext()+nextInt()/next(). - File has mixed types per line → read the whole line, then parse that line with a second
Scanner.
Key Formulas, Rules & Facts
Imports + constructors you must know
| Item | What it does | Notes |
|---|---|---|
import java.util.Scanner; | Allows Scanner | Required for Scanner |
import java.io.File; | Allows File objects | Needed for file-based Scanner |
import java.io.FileNotFoundException; | Allows handling missing file | Scanner(File) can throw it |
new Scanner(System.in) | Reads from keyboard | Doesn’t throw checked exceptions |
new Scanner(new File("x.txt")) | Reads from a file | File must exist at runtime |
Token vs line methods (know these cold)
| Method | Reads… | Common use | Gotchas |
|---|---|---|---|
next() | next token (up to whitespace) | words, simple tokens | skips leading whitespace |
nextLine() | rest of current line | full line, may include spaces | after nextInt(), can read an “empty” line |
nextInt() | next int token | numbers files | throws InputMismatchException if not an int |
nextDouble() | next double token | decimal numbers | same mismatch risk |
hasNext() | any token available? | token loops | doesn’t guarantee numeric type |
hasNextLine() | any line available? | line loops | safe for reading lines |
hasNextInt() | next token is an int? | robust int loop | avoids mismatch exception |
Exceptions you should recognize
| Exception | When it happens | How to avoid/handle |
|---|---|---|
FileNotFoundException (checked) | file path wrong / file missing | throws in method header or try/catch |
InputMismatchException | calling nextInt() on non-int token | prefer hasNextInt() or read as String then parse |
NoSuchElementException | calling next...() when nothing left | check with hasNext...() first |
IllegalStateException | using scanner after close() | don’t reuse closed scanner |
File paths (practical rules)
- Relative path (e.g.,
"data.txt") means “relative to the program’s working directory.” In many class/IDE setups, that’s the project folder. - If a file “exists” but isn’t found, it’s usually in the wrong folder at runtime.
Exam mindset: If they provide a filename, assume it’s accessible at the expected path; focus on correct reading logic and exception handling.
Delimiters (when whitespace isn’t enough)
By default, Scanner splits tokens on whitespace. You can change that:
in.useDelimiter(",");for comma-separated tokens (careful: doesn’t automatically trim spaces)in.useDelimiter("\\s*,\\s*");to split on commas and ignore surrounding spaces
Examples & Applications
Example 1: Sum of integers in a file (unknown count)
File (nums.txt):
10 20 5
7
Key idea: Use hasNextInt() so you don’t crash on non-int.
int sum = 0;
try (Scanner in = new Scanner(new File("nums.txt"))) {
while (in.hasNextInt()) {
sum += in.nextInt();
}
}
Exam variation: They may ask for average too: track count and compute sum / (double) count.
Example 2: Count lines that match a condition (line-based)
File (words.txt): one word per line, possibly blank lines.
Task: Count lines with length at least 5.
int count = 0;
try (Scanner in = new Scanner(new File("words.txt"))) {
while (in.hasNextLine()) {
String line = in.nextLine();
if (line.length() >= 5) {
count++;
}
}
}
Key insight: If blank lines matter, nextLine() preserves them as "" (empty string), which is often what you want.
Example 3: Mixed data per line (parse each line with a second Scanner)
File (grades.txt):
Ava 90 84 100
Ben 72 81
Task: Print each name with their average.
try (Scanner in = new Scanner(new File("grades.txt"))) {
while (in.hasNextLine()) {
String line = in.nextLine();
if (line.isBlank()) continue;
Scanner row = new Scanner(line);
String name = row.next();
int sum = 0;
int n = 0;
while (row.hasNextInt()) {
sum += row.nextInt();
n++;
}
row.close();
double avg = (n == 0) ? 0.0 : sum / (double) n;
System.out.println(name + ": " + avg);
}
}
Why this is powerful: You can do line-based outer loop + token-based inner parsing.
Example 4: CSV-like line with commas
Line: "Lee, 11, 12, 10"
Approach: Split on comma with trimming OR use a delimiter regex.
String line = "Lee, 11, 12, 10";
Scanner row = new Scanner(line);
row.useDelimiter("\\s*,\\s*");
String name = row.next();
int a = row.nextInt();
int b = row.nextInt();
int c = row.nextInt();
row.close();
Key insight: The delimiter "\\s*,\\s*" eats optional whitespace around commas.
Common Mistakes & Traps
Mixing
nextInt()(ornext()) withnextLine()without consuming the newline- What goes wrong:
nextLine()returns the rest of the current line (often empty). - Why:
nextInt()leaves the"\n"in the input buffer. - Fix: After
nextInt(), do one extranextLine()to consume the leftover newline before reading the next real line.
- What goes wrong:
Using
while (in.hasNextLine())but reading withnextInt()inside- What goes wrong: Your loop condition checks for lines, but you consume tokens; this can behave unpredictably and is logically mismatched.
- Fix: Match them:
hasNextInt()withnextInt(), orhasNextLine()withnextLine().
Calling
nextInt()without checkinghasNextInt()- What goes wrong:
InputMismatchExceptionif the next token isn’t an int. - Fix: Use
hasNextInt()or read asStringthen parse withInteger.parseInt(...)(and only if you know it’s valid).
- What goes wrong:
Forgetting
FileNotFoundExceptionis checked- What goes wrong: Code won’t compile if you don’t handle it.
- Fix: Either add
throws FileNotFoundExceptionto the method header or use atry/catch.
Assuming the file path is the same as where the source code is
- What goes wrong: Runtime
FileNotFoundExceptioneven though you “see the file” in your IDE. - Fix: Know the working directory (often project root). Put the file there or use the correct relative path.
- What goes wrong: Runtime
Not closing the
Scanner(resource leak)- What goes wrong: Usually not an immediate crash in small programs, but it’s bad practice and can matter.
- Fix: Use try-with-resources:
try (Scanner in = ...) { ... }.
Using
hasNext()to control numeric input loops- What goes wrong:
hasNext()may be true for a non-numeric token, thennextInt()crashes. - Fix: For ints use
hasNextInt(); for doubles usehasNextDouble().
- What goes wrong:
Expecting
Scannerto read characters one-by-one- What goes wrong:
Scanneris not character-oriented; it tokenizes. - Fix: For character-level processing, read a line with
nextLine()then usecharAt(i)in a loop.
- What goes wrong:
Memory Aids & Quick Tricks
| Trick / mnemonic | What it helps you remember | When to use it |
|---|---|---|
| “Condition matches consumption” | Your hasNextX() should match your nextX() | Prevents mismatched loops |
| “Int then Line = eat the NL” | After nextInt(), do nextLine() before reading a real line | Fixes empty-string nextLine() bug |
| “Outer lines, inner tokens” | Use nextLine() outer loop, then new Scanner(line) to parse | Mixed-format per line files |
“Use the hasNextType() guard” | Avoid InputMismatchException | Any uncertain numeric input |
Delimiter regex: \\s*,\\s* | Comma-separated values with optional spaces | Basic CSV-ish input |
Quick Review Checklist
- You can construct a
ScannerfromSystem.inand from aFile. - You remember required imports:
Scanner,File,FileNotFoundException. - You handle file input either by
throws FileNotFoundExceptionortry/catch. - You choose token (
nextInt(),next()) vs line (nextLine()) based on file format. - Your loop condition matches your read method:
hasNextInt()withnextInt(),hasNextLine()withnextLine(). - You avoid the
nextInt()→nextLine()trap by consuming the newline. - You close the scanner (best: try-with-resources).
- You can parse a complex line by creating a second
Scanneron the line.
You’ve got this—practice 2–3 file formats and you’ll be ready for whatever they throw at you.