Intermediate · Lambdas, streams and files · topic 40 of 60 · 30 min
Reading and writing files
Explanation
Paths
import java.nio.file.*;
Path data = Path.of("data", "orders.csv"); // data/orders.csv (or data\orders.csv on Windows)
System.out.println(data.getFileName()); // orders.csv
System.out.println(data.toAbsolutePath()); // full path
System.out.println(Files.exists(data)); // true or false
Path backup = data.resolveSibling("orders-backup.csv");Reading small files
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
try {
String all = Files.readString(data); // whole file as one String (UTF-8)
List<String> lines = Files.readAllLines(data, StandardCharsets.UTF_8);
System.out.println(lines.size() + " lines");
} catch (NoSuchFileException e) {
System.out.println("File not found: " + e.getFile());
} catch (IOException e) {
System.out.println("Could not read: " + e.getMessage());
}Writing files
Files.createDirectories(Path.of("reports"));
Files.writeString(Path.of("reports", "summary.txt"), "Total: Rs 1350\n"); // creates or replaces
Files.writeString(Path.of("reports", "log.txt"), "run at 10:00\n",
StandardOpenOption.CREATE, StandardOpenOption.APPEND); // append
Files.write(Path.of("reports", "cities.txt"), List.of("Pune", "Delhi", "Goa")); // one line eachBig files: stream line by line
readAllLines loads the whole file into memory: fine for a few MB, bad for a 2 GB log. Files.lines returns a lazy Stream<String> that reads as you go. It holds the file open, so use try-with-resources. BufferedReader with readLine is the classic alternative.
try (Stream<String> lines = Files.lines(Path.of("access.log"))) {
long serverErrors = lines.filter(l -> l.contains(" 500 ")).count();
System.out.println("500 errors: " + serverErrors);
}
try (BufferedWriter w = Files.newBufferedWriter(Path.of("out.csv"))) {
w.write("id,amount");
w.newLine();
}Parsing a CSV into records
record Student(String name, String city, int marks) {}
List<Student> students;
try (Stream<String> lines = Files.lines(Path.of("students.csv"))) {
students = lines.skip(1) // skip the header row
.filter(l -> !l.isBlank())
.map(l -> l.split(","))
.map(p -> new Student(p[0].strip(), p[1].strip(), Integer.parseInt(p[2].strip())))
.toList();
}Character encodings
Text files store characters as bytes using an encoding. UTF-8 handles every language, including Hindi, Tamil and emoji. Files.readString/writeString default to UTF-8; older APIs like FileReader used the platform default, which on some Windows systems was not UTF-8 before Java 18 made UTF-8 the default. When text from other systems looks garbled ("é"), an encoding mismatch is usually the cause.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Reading and writing files · 1/6
In this lesson you will read and write files with java dot nio dot file.
Prefer a video by a teacher? Find free videos on “java nio files readString write lines path tutorial csv” on YouTube ↗
In real life: A daily sales report from a CSV
A chain of medical shops uploads one CSV of the day's bills per branch. A Java job reads each file with Files.lines, parses the rows into records, totals the sales per branch with groupingBy, and writes a summary file that the owner receives every morning.
record Bill(String branch, double amount) {}
Map<String, Double> totals;
try (Stream<String> lines = Files.lines(Path.of("bills-2026-10-19.csv"))) {
totals = lines.skip(1)
.map(l -> l.split(","))
.map(p -> new Bill(p[0], Double.parseDouble(p[1])))
.collect(Collectors.groupingBy(Bill::branch, TreeMap::new, Collectors.summingDouble(Bill::amount)));
}
StringBuilder out = new StringBuilder();
totals.forEach((b, t) -> out.append(String.format("%s,%.2f%n", b, t)));
Files.writeString(Path.of("summary-2026-10-19.csv"), out);Practice (0/3 done)
Which is the best choice for counting matching lines in a 3 GB log file?
The same CSV parsing logic in JavaScript, which runs here: write parseStudents(csvText) that skips the header line and blank lines, splits each row on commas, trims the parts and returns objects { name, city, marks } with marks as a number.
Write a Java program that reads students.csv (name,city,marks) with Files.lines in try-with-resources, parses it into a record Student, prints the average marks per city with groupingBy and averagingInt, and writes the result to city-averages.txt with Files.write. Handle a missing file with a friendly message.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Method referencesLambdas, streams and files · same module
- CSV files and simple statisticsPython Programming · Working with data
- Reading CSV and JSON with the standard libraryData Science, Machine Learning and AI · Python for data
- Working with filesPython Programming · Working with data
- Files and a tiny server in NodeJavaScript Programming (language in depth) · Performance and Node.js
- Slices and stringsRust Programming · Borrowing, slices and lifetimes
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Which method reads a whole small text file into one String (Java 11+)?
Answer: Files.readString
Files.readString reads the full content as UTF-8 by default.
Why must Files.lines be used with try-with-resources?
Answer: It keeps the file open until the stream is closed
The stream holds a file handle.
Which encoding handles Hindi, Tamil and English together?
Answer: UTF-8
UTF-8 covers all Unicode characters.
Files.writeString(path, text) on an existing file, with no options…
Answer: Replaces the content
The default options create or truncate; use APPEND to add.
What does csv.DictReader give you for each row?Related
Answer: A dict with the header names as keys
DictReader uses the header row as keys, so you can write row["marks"].
Why not read CSV lines with line.split(",")?Related
Answer: Quoted values that contain commas, like "Mumbai, MH", get broken into two columns
The csv module understands quotes; a plain split does not.
Which mode adds new text to the end of a file and keeps the old text?Related
Why use a stream for a 5 GB log file?Related
Answer: It processes chunks without loading the whole file into memory
Streams keep memory use small.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- This is the last topic of “Lambdas, streams and files”. The module exam comes next.
- Module 8 exam: Lambdas, streams and files · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Multithreading and concurrency. 60 topics left in the course before the final exam.