Path and Files API
Navigate and manipulate the filesystem using java.nio.file.Path, Files, and directory operations.
Overview
Key Points
- •Path.of("dir/file.txt") creates a path; Paths.get() is the older equivalent
- •path.getFileName(), getParent(), getRoot() decompose the path
- •path.resolve("subdir") appends a relative path
- •path.relativize(other) computes the relative path between two paths
- •path.toAbsolutePath() converts to absolute path
- •Files.exists(path), Files.isDirectory(path), Files.isRegularFile(path) check properties
- •Files.createDirectory(path), Files.createDirectories(path) create directories
- •Files.copy(src, dst), Files.move(src, dst) copy and move files
- •Files.delete(path), Files.deleteIfExists(path) delete files or directories
- •Files.list(dir) lists directory contents; Files.walk(dir) walks recursively
Examples
Path operations
import java.nio.file.*;
public class Main {
public static void main(String[] args) {
Path p = Path.of("projects", "myapp", "src", "Main.java");
System.out.println("Path: " + p);
System.out.println("File name: " + p.getFileName()); // Main.java
System.out.println("Parent: " + p.getParent()); // projects/myapp/src
System.out.println("Parts: " + p.getNameCount()); // 4
System.out.println("Part 0: " + p.getName(0)); // projects
System.out.println("Absolute: " + p.toAbsolutePath());
// Resolve: append a path
Path dir = Path.of("projects/myapp");
Path resolved = dir.resolve("src/Main.java");
System.out.println("Resolved: " + resolved); // projects/myapp/src/Main.java
// Relativize: compute relative path between two paths
Path from = Path.of("/home/user");
Path to = Path.of("/home/user/docs/report.txt");
System.out.println("Relative: " + from.relativize(to)); // docs/report.txt
// Normalize: collapse ..
Path ugly = Path.of("/home/user/../user/docs/../docs/file.txt");
System.out.println("Normalized:" + ugly.normalize()); // /home/user/docs/file.txt
}
}Path.of() is the modern replacement for new File(). Paths are immutable, so operations like resolve() and normalize() return new Path instances.
File and directory management
import java.io.IOException;
import java.nio.file.*;
public class Main {
public static void main(String[] args) throws IOException {
Path tmpDir = Files.createTempDirectory("demo");
// Create subdirectory structure
Path subDir = tmpDir.resolve("data/reports");
Files.createDirectories(subDir); // creates all missing parents
System.out.println("Directory created: " + Files.isDirectory(subDir));
// Write a file
Path file1 = subDir.resolve("q1.txt");
Files.writeString(file1, "Q1 report data");
// Copy
Path file2 = subDir.resolve("q1-backup.txt");
Files.copy(file1, file2);
System.out.println("Backup exists: " + Files.exists(file2));
// Move
Path file3 = tmpDir.resolve("archived-q1.txt");
Files.move(file2, file3, StandardCopyOption.REPLACE_EXISTING);
System.out.println("After move, backup exists: " + Files.exists(file2));
System.out.println("Archive exists: " + Files.exists(file3));
// File info
System.out.println("File size: " + Files.size(file1) + " bytes");
System.out.println("Last modified: " + Files.getLastModifiedTime(file1));
// Cleanup
Files.walk(tmpDir)
.sorted(java.util.Comparator.reverseOrder()) // delete files before dirs
.forEach(p -> { try { Files.delete(p); } catch (IOException e) {} });
}
}Files.createDirectories() creates the full path including missing parent directories. Files.copy() requires StandardCopyOption.REPLACE_EXISTING if the destination already exists.
Listing and walking directories
import java.io.IOException;
import java.nio.file.*;
public class Main {
public static void main(String[] args) throws IOException {
Path tmpDir = Files.createTempDirectory("tree");
Files.createDirectories(tmpDir.resolve("src/main"));
Files.createDirectories(tmpDir.resolve("src/test"));
Files.writeString(tmpDir.resolve("src/main/App.java"), "// main");
Files.writeString(tmpDir.resolve("src/test/AppTest.java"), "// test");
Files.writeString(tmpDir.resolve("README.md"), "# readme");
// List direct children only
System.out.println("Direct children:");
try (var stream = Files.list(tmpDir)) {
stream.forEach(p -> System.out.println(" " + p.getFileName()));
}
// Walk entire tree (recursive)
System.out.println("All files:");
try (var stream = Files.walk(tmpDir)) {
stream.filter(Files::isRegularFile)
.forEach(p -> System.out.println(" " + tmpDir.relativize(p)));
}
// Cleanup
Files.walk(tmpDir)
.sorted(java.util.Comparator.reverseOrder())
.forEach(p -> { try { Files.delete(p); } catch (IOException e) {} });
}
}Files.list() returns a Stream<Path> of direct children. Files.walk() returns the directory itself and all descendants. Both must be closed with try-with-resources.
Common Mistakes
- Using old java.io.File instead of java.nio.file.Path. File has poor error reporting (returns false on failure instead of throwing) and limited functionality
- Forgetting to close Files.list() and Files.walk() streams. They hold directory handles
- Deleting a non-empty directory with Files.delete(). This throws DirectoryNotEmptyException. Walk the tree and delete files first, then directories in reverse order
Note
To delete a directory tree recursively, use Files.walk(dir).sorted(Comparator.reverseOrder()).forEach(Files::delete). Reverse order ensures files are deleted before their parent directories.
Exercises
Write Java code and click Run to execute it instantly. When your output looks correct, mark as done.
Completed: 0 / 4 exercises
Knowledge Check
Question 1 of 4