8.4 Directories, Encoding, and File Management
Many file bugs come from the "around the file" details: the path is not where you think, the parent folder does not exist, the encoding is different, or a file-management operation overwrites important data.
Relative Paths and the Current Working Directory
A relative path is not automatically relative to the Java source file. It is relative to the current working directory, usually the directory where you run java.
Path path = Path.of("data", "quotes.txt");
String content = Files.readString(path, StandardCharsets.UTF_8);If the current working directory is the project root, Java looks for:
project/
data/
quotes.txtBut if you run the program from another directory, the same relative path may not be found.
NoSuchFileException, first check where the program is starting its file search. Print Path.of("").toAbsolutePath() to inspect the current working directory.Creating Directories
Writing reports/summary.txt fails if reports does not exist. Create parent directories first.
Path folder = Path.of("reports");
Files.createDirectories(folder);
Path report = folder.resolve("summary.txt");
Files.writeString(report, "Report ready" + System.lineSeparator(), StandardCharsets.UTF_8);createDirectories() is different from "create one folder only." It creates missing parent directories too, and it does nothing if the directory already exists.
UTF-8 Encoding
Text files store bytes. Encoding converts between characters and bytes. UTF-8 is one of the most common and compatible text encodings.
Path path = Path.of("note.txt");
Files.writeString(path, "Hello, Java!", StandardCharsets.UTF_8);
System.out.println(Files.readString(path, StandardCharsets.UTF_8));If writing and reading use different encodings, plain English may appear fine, but non-English text and symbols can break. Use StandardCharsets.UTF_8 in examples unless you have a specific reason not to.
Listing, Copying, Moving, and Deleting
Files can inspect and manage files:
Path path = Path.of("note.txt");
System.out.println(Files.exists(path));
System.out.println(Files.size(path));
System.out.println(Files.isRegularFile(path));Directory listing uses a stream, which must be closed. Try-with-resources handles that.
try (var entries = Files.list(Path.of("reports"))) {
entries.forEach(System.out::println);
}Common management methods:
Files.copy(source, target): copy a file.Files.move(source, target): move or rename a file.Files.delete(path): delete and fail if the file does not exist.Files.deleteIfExists(path): delete only when present.
These operations can overwrite, fail, or remove data. Treat them with care.