Working with Files
Programs read configuration, import CSV data, write reports and logs. The modern java.nio.file API — built around Path and the Files utility class — makes reading, writing, copying and listing files short and safe.
Paths
import java.nio.file.Path; public class Main { public static void main(String[] args) { Path report = Path.of("reports", "2026", "march.csv"); System.out.println(report); System.out.println(report.getFileName()); System.out.println(report.getParent()); System.out.println(report.resolveSibling("april.csv")); System.out.println(report.toString().endsWith(".csv")); } }
reports/2026/march.csv march.csv reports/2026 reports/2026/april.csv true
Path.of joins parts with the right separator for the operating system (/ on macOS and Linux, \ on Windows). A Path is just a description; the file doesn't have to exist.
Writing and reading text
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.List; public class Main { public static void main(String[] args) throws IOException { Path notes = Path.of("notes.txt"); Files.writeString(notes, "Buy milk\n"); Files.writeString(notes, "Call Ana\n", StandardOpenOption.APPEND); Files.write(notes, List.of("Book dentist"), StandardOpenOption.APPEND); String all = Files.readString(notes); System.out.print(all); List<String> lines = Files.readAllLines(notes); System.out.println(lines.size() + " lines, size " + Files.size(notes) + " bytes"); Files.delete(notes); System.out.println(Files.exists(notes)); } }
Buy milk Call Ana Book dentist 3 lines, size 31 bytes false
writeString and readString handle a whole file at once, using UTF-8 by default. StandardOpenOption.APPEND adds to the end instead of replacing the content. These methods throw the checked IOException, which main declares here.
Processing large files line by line
import java.io.BufferedReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.stream.Stream; public class Main { public static void main(String[] args) throws IOException { Path log = Files.createTempFile("app", ".log"); Files.writeString(log, "INFO start\nERROR disk full\nINFO retry\nERROR timeout\n"); try (Stream<String> lines = Files.lines(log)) { System.out.println(lines.filter(l -> l.startsWith("ERROR")).count() + " errors"); } try (BufferedReader reader = Files.newBufferedReader(log)) { String first = reader.readLine(); System.out.println("First line: " + first); } Files.delete(log); } }
2 errors First line: INFO start
readString loads everything into memory. For big files, stream the lines with Files.lines (in try-with-resources, since it keeps the file open) or a BufferedReader.
Reading a CSV file
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; record Sale(String product, int quantity, double price) { double total() { return quantity * price; } } public class Main { public static void main(String[] args) throws IOException { Path csv = Files.createTempFile("sales", ".csv"); Files.writeString(csv, """ product,quantity,price Mug,4,12.50 Lamp,1,34.00 Throw,2,49.00 """); List<Sale> sales = Files.readAllLines(csv).stream() .skip(1) .map(line -> line.split(",")) .map(f -> new Sale(f[0], Integer.parseInt(f[1]), Double.parseDouble(f[2]))) .toList(); sales.forEach(s -> System.out.println("%-6s %7.2f".formatted(s.product(), s.total()))); System.out.println("Total: %.2f".formatted(sales.stream().mapToDouble(Sale::total).sum())); Files.delete(csv); } }
Mug 50.00 Lamp 34.00 Throw 98.00 Total: 182.00
Splitting on commas works for simple files. Real CSV data can contain quoted commas and line breaks — use a library such as Apache Commons CSV or OpenCSV for that.
Directories, copying and moving
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.Comparator; import java.util.stream.Stream; public class Main { public static void main(String[] args) throws IOException { Path root = Files.createTempDirectory("demo"); Path docs = Files.createDirectories(root.resolve("docs/2026")); Path a = Files.writeString(docs.resolve("a.txt"), "alpha"); Files.copy(a, docs.resolve("b.txt")); Files.move(docs.resolve("b.txt"), root.resolve("b-moved.txt"), StandardCopyOption.REPLACE_EXISTING); try (Stream<Path> files = Files.walk(root)) { files.filter(Files::isRegularFile) .map(p -> root.relativize(p).toString()) .sorted() .forEach(System.out::println); } try (Stream<Path> all = Files.walk(root)) { all.sorted(Comparator.reverseOrder()).forEach(p -> p.toFile().delete()); } System.out.println(Files.exists(root)); } }
b-moved.txt docs/2026/a.txt false
Files also has list (one folder), walk (recursive), isDirectory, getLastModifiedTime and more. Deleting a folder requires deleting its contents first — hence walking in reverse order.
Handling errors
import java.io.IOException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; public class Main { public static void main(String[] args) { try { Files.readString(Path.of("missing-settings.json")); } catch (NoSuchFileException e) { System.out.println("Not found: " + e.getMessage()); } catch (IOException e) { System.out.println("Could not read: " + e); } } }
Not found: missing-settings.json
Try it yourself
Write a word list to a temporary file, then read it back and report the longest word.
Longest word: mountain