Files and paths
Modern Java has two main tools for files, both from the java.nio.file package. Path is a path to a file or folder — just an address that may not even exist. Files is a set of static methods that do things with files: create, copy, delete, read.
A path
A path is created with Path.of. You can pass the parts separately — Java joins them with the separator used by the operating system:
void main() {
Path path = Path.of("docs", "2026", "report.txt");
IO.println(path.getFileName());
IO.println(path.getParent().getFileName());
}Output:
report.txt
2026The path docs/2026/report.txt is relative: it starts from the current folder the program was launched from. An absolute path starts from the root of the drive; toAbsolutePath() returns it. All examples in this lesson use relative paths and create the files they need themselves.
Does the file exist
A Path on its own knows nothing about the disk. To check a file you need the Files class:
void main() throws IOException {
Path path = Path.of("hello.txt");
IO.println(Files.exists(path));
Files.writeString(path, "Hello, €!");
IO.println(Files.exists(path));
IO.println(Files.size(path) + " bytes");
}Output:
false
true
11 bytesFiles.writeString creates the file and writes a string into it. The size is 11 bytes: in UTF-8 Latin letters take one byte each, while the euro sign takes three.
Folders
Files.createDirectories creates a folder along with all missing parent folders. Files.isDirectory and Files.isRegularFile tell a folder from an ordinary file:
void main() throws IOException {
Path dir = Path.of("photos", "summer");
Files.createDirectories(dir);
Path photo = dir.resolve("sea.jpg");
Files.writeString(photo, "...");
IO.println(photo);
IO.println(Files.isDirectory(dir));
IO.println(Files.isRegularFile(photo));
}Output (on Windows the separator is \):
photos/summer/sea.jpg
true
trueThe resolve method appends one more part to a path — handier than gluing strings by hand.
Copying, moving, deleting
void main() throws IOException {
Path original = Path.of("notes.txt");
Files.writeString(original, "Plan for the week");
Path copy = Files.copy(original, Path.of("notes-copy.txt"), StandardCopyOption.REPLACE_EXISTING);
Path moved = Files.move(copy, Path.of("archive.txt"), StandardCopyOption.REPLACE_EXISTING);
IO.println(Files.exists(copy));
IO.println(Files.readString(moved));
Files.delete(moved);
IO.println(Files.exists(moved));
}Output:
false
Plan for the week
falseWithout StandardCopyOption.REPLACE_EXISTING, copy and move throw an exception if the target file already exists. Files.deleteIfExists deletes a file without an error if it isn't there.
Listing files
Files.list returns a stream of the paths inside a folder. The order of files depends on the operating system, so it's better to sort the result. The stream keeps the folder open, so it is closed with try-with-resources:
void main() throws IOException {
Path dir = Files.createDirectories(Path.of("inbox"));
for (String name : List.of("b.txt", "a.txt", "c.log")) {
Files.writeString(dir.resolve(name), name);
}
try (Stream<Path> files = Files.list(dir)) {
files.map(p -> p.getFileName().toString())
.filter(name -> name.endsWith(".txt"))
.sorted()
.forEach(IO::println);
}
}Output:
a.txt
b.txtTo go through all nested folders too, use Files.walk — it works the same way but goes deeper.
Common mistake
Files.delete doesn't delete a folder that isn't empty — you have to delete everything inside first:
void main() throws IOException {
Path dir = Files.createDirectories(Path.of("tmp"));
Files.writeString(dir.resolve("data.txt"), "1");
Files.delete(dir);
}Output:
Exception in thread "main" java.nio.file.DirectoryNotEmptyException: tmp
at Main.main(Main.java:5)Delete the contents, then the folder itself. For a tree of folders, walk it with Files.walk in reverse order so that files are deleted before their folders.