Programs that forget everything when they close have limited uses. Saving a game, keeping a log of what happened, loading settings, importing a spreadsheet exported as CSV, or writing a report for someone to open later: all of these need files.
Modern Java handles files with the java.nio.file package, built around two classes. Path represents the location of a file or folder, and Files has static methods to read, write, copy, move and inspect them. For most everyday tasks, a single method call is enough.
In this lesson you'll read and write whole files, append to a log, process a big file line by line without loading it all into memory, parse CSV data into objects, and deal with the IOException that every file operation can throw, because files can always be missing, locked or unreadable.
Paths
import java.nio.file.Path;
Path notes = Path.of("notes.txt"); // relative to where the program runs
Path report = Path.of("reports", "2024", "july.csv");
System.out.println(report.getFileName()); // july.csvPath.of()builds a path from one or more parts, using the right separator for the operating system.- A relative path like
notes.txtis found from the folder where the program was started. - An absolute path starts from the top of the drive, such as
C:\data\notes.txtor/home/sam/notes.txt. Avoid hard-coding these, because they won't exist on other computers.
Reading and writing whole files
| Task | Method |
|---|---|
| Read all text | Files.readString(path) |
| Read as a list of lines | Files.readAllLines(path) |
| Write text (replacing the file) | Files.writeString(path, text) |
| Write a list of lines | Files.write(path, lines) |
| Add to the end | Files.writeString(path, text, StandardOpenOption.CREATE, StandardOpenOption.APPEND) |
Writing replaces the file's contents unless you pass APPEND. These methods use UTF-8 by default, which handles every language's characters. They're perfect for small and medium files; for very large ones, read line by line instead.
Large files, readers and writers
Files.lines(path) returns a stream of lines that are read only as needed, so even a huge log file uses little memory. Because it holds the file open, use it in try-with-resources, which closes the file automatically:
try (Stream<String> lines = Files.lines(Path.of("server.log"))) {
long errors = lines.filter(l -> l.contains("ERROR")).count();
}Files.newBufferedReader(path) and Files.newBufferedWriter(path) give you a reader with readLine() and a writer with write() and newLine(), for when you want full control. They also belong in try-with-resources.
Checking files and handling errors
Files.exists(path)andFiles.isDirectory(path)check what's there.Files.createDirectories(path)creates a folder and any missing parents.Files.size(path),Files.copy(a, b),Files.move(a, b)andFiles.delete(path)do what they say.
Almost every Files method throws IOException, a checked exception: Java makes you either catch it or declare throws IOException. A missing file throws NoSuchFileException, a subclass of IOException, so you can give a clear message.
Listing and walking folders
To see what's inside a folder, Files.list(folder) gives a stream of the paths directly inside it, and Files.walk(folder) also goes into every subfolder. Both hold the folder open, so use them in try-with-resources:
try (Stream<Path> files = Files.list(Path.of("reports"))) {
List<Path> csvFiles = files
.filter(p -> p.toString().endsWith(".csv"))
.sorted()
.toList();
System.out.println(csvFiles);
}This pattern, list the files, keep the ones you want and process each in turn, is the basis of many batch jobs, such as importing every CSV file that arrived overnight.
Text encodings
A file stores bytes, not characters. An encoding decides how characters such as é, £ or 日 become bytes. The Files methods use UTF-8 by default, which can represent every character and is the standard on the web. If you read a file written in a different encoding, accented letters turn into odd symbols. Pass the encoding explicitly when you know it: Files.readString(path, StandardCharsets.ISO_8859_1). Since Java 18, the older FileReader and FileWriter classes also default to UTF-8 rather than the operating system's setting.
Java Files Syntax
File essentials
import java.nio.file.*;
Path p = Path.of("folder", "file.txt");
String all = Files.readString(p);
List<String> lines = Files.readAllLines(p);
Files.writeString(p, "text");
Files.writeString(p, "more\n", StandardOpenOption.CREATE, StandardOpenOption.APPEND);
try (Stream<String> s = Files.lines(p)) { ... }
Files.exists(p); Files.createDirectories(dir);Java Files Summary
Path.of(...)represents a file location;Fileshas static methods to work with it.- readString and readAllLines read whole files; writeString and write create or replace them.
- Pass StandardOpenOption.APPEND to add to a file instead of replacing it.
- Use Files.lines or a BufferedReader in try-with-resources for large files.
- File methods throw the checked IOException, so catch it or declare it.
Java Files Examples
Each example shows the code, the output it produces and what each part does.
Saving and loading notes
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
Path file = Path.of("notes.txt");
Files.write(file, List.of("Buy milk", "Call Sam", "Book dentist"));
List<String> notes = Files.readAllLines(file);
System.out.println("You have " + notes.size() + " notes:");
for (int i = 0; i < notes.size(); i++) {
System.out.println((i + 1) + ". " + notes.get(i));
}
System.out.println("Saved? " + Files.exists(file));
}
}You have 3 notes:
1. Buy milk
2. Call Sam
3. Book dentist
Saved? trueLine-by-line explanation
- Line 7Declaring throws IOException passes any file error up and stops the program with a message.
- Line 9write creates the file, or replaces it, with one line per item.
- Line 11readAllLines gives back a List with one String per line.
- Line 16Files.exists confirms the file is really on disk.
Appending to a log and counting errors
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.stream.Stream;
public class Main {
static void log(Path file, String message) throws IOException {
Files.writeString(file, message + "\n",
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
}
public static void main(String[] args) throws IOException {
Path file = Path.of("app.log");
Files.deleteIfExists(file);
log(file, "INFO Started");
log(file, "ERROR Payment timeout");
log(file, "INFO Order 1042 saved");
log(file, "ERROR Disk nearly full");
try (Stream<String> lines = Files.lines(file)) {
lines.filter(line -> line.startsWith("ERROR"))
.forEach(System.out::println);
}
}
}ERROR Payment timeout
ERROR Disk nearly fullLine-by-line explanation
- Lines 9 to 10CREATE makes the file if it's missing, and APPEND adds to the end instead of replacing it.
- Line 15Start fresh each time the example runs.
- Lines 21 to 24Files.lines reads lazily, and try-with-resources closes the file afterwards.
Reading a CSV file into records
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
public class Main {
record Product(String name, double price, int stock) {}
public static void main(String[] args) {
Path csv = Path.of("products.csv");
try {
Files.writeString(csv, "name,price,stock\nPen,1.20,300\nBackpack,34.99,15\nLamp,24.50,22\n");
List<Product> products = new ArrayList<>();
for (String line : Files.readAllLines(csv).subList(1, 4)) {
String[] parts = line.split(",");
products.add(new Product(parts[0], Double.parseDouble(parts[1]),
Integer.parseInt(parts[2])));
}
double value = 0;
for (Product p : products) {
value += p.price() * p.stock();
}
System.out.printf("%d products, stock worth £%.2f%n", products.size(), value);
Files.readString(Path.of("missing.csv"));
} catch (NoSuchFileException e) {
System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.out.println("Couldn't read the file: " + e.getMessage());
}
}
}3 products, stock worth £1423.85
File not found: missing.csvLine-by-line explanation
- Line 14Create a small CSV file to read. In real use, it would come from a spreadsheet.
- Line 17subList(1, 4) skips the header row.
- Lines 18 to 20Split each line on commas and convert the text into numbers.
- Line 28Reading a file that doesn't exist throws NoSuchFileException.
- Lines 29 to 33Catch the specific exception first, then the general IOException.
Common Java Files Mistakes
Overwriting when you meant to append
Files.writeString(log, "New entry\n"); // previous entries are goneFiles.writeString(log, "New entry\n", StandardOpenOption.CREATE, StandardOpenOption.APPEND);Leaving Files.lines open
long count = Files.lines(path).count(); // file stays opentry (Stream<String> lines = Files.lines(path)) {
long count = lines.count();
}Hard-coded absolute paths
Path p = Path.of("C:\\Users\\sam\\Desktop\\data.csv");Path p = Path.of("data", "data.csv"); // relative to the program's folderJava Files in Real Projects
Files in real applications
Servers write log files line by line and rotate them each day, desktop applications save documents and settings, data tools import CSV exports from spreadsheets and banks, and build tools read configuration files. Larger systems move to databases, but files remain the simplest way to save data and exchange it with other programs.
Java Files FAQ
Where does Java look for a relative file path?
In the working directory: the folder the program was started from, not the folder containing the .java file. IDEs usually start programs in the project's root folder. Print Path.of("").toAbsolutePath() to see the folder your program is actually using.
What is the difference between File and Path in Java?
java.io.File is the original class from Java 1.0. Path, used with the Files class, arrived in Java 7 and has clearer methods and better error messages. Prefer Path in new code. When an older library needs a File, convert with path.toFile(), and convert back with file.toPath().
How do I read a file line by line in Java?
For small files, Files.readAllLines(path) returns a list of lines. For large files, use Files.lines(path) in try-with-resources, or a BufferedReader from Files.newBufferedReader(path) with a while ((line = reader.readLine()) != null) loop. Both read one line at a time without loading the whole file.
Should I check that a file exists before reading it?
It's often better simply to read it and catch NoSuchFileException. Between a check and the read, another program could delete or create the file, so the check doesn't guarantee anything. Files.exists is still useful to decide, for example, whether to create a default settings file.
How do I read a file packaged inside my JAR?
Files bundled with your program, such as src/main/resources/config.json, aren't ordinary files once packaged. Read them with getClass().getResourceAsStream("/config.json"), which returns an InputStream, or with getResource for a URL. Path.of only works for files on the disk.
Java Files Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the line that reads a whole file into one String.
String text = Files.(Path.of("story.txt"));
What happens to a file's contents when you call Files.writeString(path, "hi")?
Which is best for counting lines in a 5 GB log file?
What kind of exception is IOException?
A file contains three lines. What does Files.readAllLines(p).get(3) do?
Java Files Quiz
5 questions to check what you learned.
Which class represents a file's location?
- File
- Folder
- Path
- Location
What does try-with-resources do?
- Closes the resource automatically, even if an exception happens
- Retries an operation
- Opens several files at once
- Hides exceptions
Which exception means the file wasn't found?
- FileMissingError
- NoSuchFileException
- NullPointerException
- EOFException
What does
Files.createDirectories(Path.of("a", "b"))do?- Creates a file called b
- Deletes the folders
- Lists the folders
- Creates folder a and folder b inside it, if they're missing
Why avoid hard-coding a path like C:\Users\sam\data.csv?
- Backslashes aren't allowed
- Java can't read the C drive
- That location won't exist on other people's computers or servers
- Absolute paths are slower