Crash Courses · PhD
Exception Handling & File I/O
Write robust exception handling with try/catch/finally, define custom exceptions, and read/write files with modern Java NIO.
20 min read+185 XP on completionCert: Java / Kotlin Crash Course
Tap any word in the text below to start reading from there.
Exception Handling & File I/O
The Exception Hierarchy
Throwable
├── Error (JVM-level — OutOfMemoryError — don't catch these)
└── Exception
├── Checked Exceptions (must handle at compile time)
│ ├── IOException
│ ├── SQLException
│ └── ParseException
└── RuntimeException (unchecked — handle if you want)
├── NullPointerException
├── ArrayIndexOutOfBoundsException
├── IllegalArgumentException
└── NumberFormatException---
try / catch / finally
public static int divide(int a, int b) {
try {
return a / b;
} catch (ArithmeticException e) {
System.err.println("Division by zero: " + e.getMessage());
return 0;
} finally {
System.out.println("divide() completed"); // always runs
}
}
// Multiple catch blocks — most specific first:
public static int parseAndDouble(String input) {
try {
int n = Integer.parseInt(input);
return n * 2;
} catch (NumberFormatException e) {
System.err.println("Not a number: " + input);
return -1;
} catch (Exception e) {
System.err.println("Unexpected: " + e.getMessage());
return -1;
}
}
// Multi-catch (Java 7+):
try {
// ...
} catch (IOException | SQLException e) {
System.err.println("IO or DB error: " + e.getMessage());
}---
Custom Exceptions
// Checked custom exception
public class InsufficientFundsException extends Exception {
private final double requested;
private final double available;
public InsufficientFundsException(double requested, double available) {
super(String.format("Requested $%.2f but only $%.2f available",
requested, available));
this.requested = requested;
this.available = available;
}
public double getShortfall() { return requested - available; }
}
// Using it:
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException(amount, balance);
}
balance -= amount;
}
// Caller must handle:
try {
account.withdraw(5000.0);
} catch (InsufficientFundsException e) {
System.err.println(e.getMessage());
System.out.printf("You need $%.2f more.%n", e.getShortfall());
}---
File I/O with java.nio.file
Modern Java uses Path and Files from java.nio.file:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
// Writing a file:
public static void writeReport(String filepath, String content) throws IOException {
Path path = Paths.get(filepath);
Files.writeString(path, content);
System.out.println("Written to: " + path.toAbsolutePath());
}
// Reading a file:
public static List<String> readLines(String filepath) throws IOException {
return Files.readAllLines(Paths.get(filepath));
}
// Streaming lines (memory-efficient for large files):
public static long countWords(String filepath) throws IOException {
try (var lines = Files.lines(Paths.get(filepath))) {
return lines
.flatMap(line -> java.util.Arrays.stream(line.split("\\s+")))
.filter(word -> !word.isBlank())
.count();
}
}---
try-with-resources
The safest way to work with resources (files, database connections, network streams):
import java.io.*;
import java.nio.file.*;
// try-with-resources ensures reader.close() is ALWAYS called
public static void processCSV(String filepath) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(Paths.get(filepath))) {
String line;
int lineNum = 0;
while ((line = reader.readLine()) != null) {
lineNum++;
String[] parts = line.split(",");
if (parts.length < 3) continue;
System.out.printf("Line %d: name=%s, score=%s%n",
lineNum, parts[0].trim(), parts[2].trim());
}
}
// reader is automatically closed here — no finally block needed
}
// Writing CSV:
public static void writeCSV(String filepath, List<String[]> rows) throws IOException {
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Paths.get(filepath)))) {
writer.println("name,email,score");
for (String[] row : rows) {
writer.println(String.join(",", row));
}
}
}---
Exception Design Guidelines
- Throw early, catch late — validate inputs immediately; handle exceptions at the layer that can do something meaningful
- Never swallow exceptions —
catch (Exception e) {}hides bugs; at minimum log the error - Use checked exceptions for conditions the caller can reasonably recover from (file not found → prompt for different path)
- Use unchecked exceptions for programming errors (invalid argument, null where not expected)
- Include context in exception messages —
"File not found: " + filepathis better than"File not found"
Reading progress
0% read
In this module
Checked Exception
Unchecked Exception
try-with-resources
Finally block
0%