1. Creating directories
A directory (aka folder) is not just a container for files, but the foundation of how data is organised on a disk. In applications, we constantly create directories for input/output data, logs, temporary files, etc. The modern java.nio.file API makes this convenient and cross-platform.
Let’s see how to create, delete, and list folder contents using the Files, Path, and Paths classes.
Files.createDirectory(path)
Creates a single directory at the specified path. If the parent directory is missing, an exception will be thrown.
import java.nio.file.*;
public class DirectoryDemo {
public static void main(String[] args) throws Exception {
Path dir = Paths.get("testDir");
if (!Files.exists(dir)) {
Files.createDirectory(dir);
System.out.println("Directory created: " + dir.toAbsolutePath());
} else {
System.out.println("Directory already exists: " + dir.toAbsolutePath());
}
}
}
If you try to create a directory that already exists, you will get a FileAlreadyExistsException.
Files.createDirectories(path)
Creates the entire chain of directories. If any intermediate directory is missing, it will be created automatically. If part of the chain already exists, no error will be thrown.
Path nestedDir = Paths.get("parent/child/grandchild");
Files.createDirectories(nestedDir);
System.out.println("Directory chain created: " + nestedDir.toAbsolutePath());
It’s like asking Java to build not only the house but also the entryway and the street if they didn’t exist yet.
Typical example: create a project structure
Suppose you need to save reports into the output/reports/2024 folder. Don’t check each directory manually — use createDirectories.
Path reportsPath = Paths.get("output/reports/2024");
Files.createDirectories(reportsPath);
Java will figure out what already exists and what needs to be created.
2. Deleting files and directories
Files.delete(path)
Deletes a file or an empty directory. If the directory isn’t empty, a DirectoryNotEmptyException will be thrown.
Path dir = Paths.get("testDir");
try {
Files.delete(dir);
System.out.println("Directory deleted: " + dir.toAbsolutePath());
} catch (DirectoryNotEmptyException e) {
System.out.println("Cannot delete: directory is not empty!");
}
Files.deleteIfExists(path)
Works like delete, but doesn’t throw an error if the object doesn’t exist. Returns true if something was deleted and false if the object wasn’t there.
Path file = Paths.get("output/reports/2024/report.txt");
if (Files.deleteIfExists(file)) {
System.out.println("File deleted.");
} else {
System.out.println("File not found, nothing deleted.");
}
How to delete a non-empty directory?
You cannot delete a non-empty folder as-is. First you need to delete all its contents (files and subdirectories), and then delete the folder itself. This is done recursively, for example, via Files.walkFileTree:
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
public class DeleteDirectoryRecursively {
public static void main(String[] args) throws IOException {
Path dir = Paths.get("parent");
if (Files.exists(dir)) {
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
System.out.println("The directory and all its contents have been deleted.");
}
}
}
If you’re just starting out, don’t be intimidated by this code — we’ll discuss walkFileTree later.
3. Listing directory contents
Files.list(path)
Returns a Stream<Path> — a stream of paths. You can process folder contents via the Stream API. Each entry is a file or a subdirectory (no recursion!).
Path dir = Paths.get("output/reports");
if (Files.exists(dir) && Files.isDirectory(dir)) {
try (var stream = Files.list(dir)) {
stream.forEach(path -> System.out.println(path.getFileName()));
}
}
Important detail: you must close the stream, so use try-with-resources.
Example: print file and subdirectory names
Path reports2024 = Paths.get("output/reports/2024");
try (var stream = Files.list(reports2024)) {
stream.forEach(path -> {
String type = Files.isDirectory(path) ? "directory" : "file";
System.out.println(path.getFileName() + " — " + type);
});
}
Getting the list of files as a collection
List<Path> files = Files.list(reports2024)
.filter(Files::isRegularFile)
.toList();
System.out.println("Files in the folder:");
files.forEach(System.out::println);
Important: Files.list(path) returns only the contents of the current directory (top level). For recursive traversal use Files.walk(path).
4. Practice: mini file manager
The utility creates the mydata/logs directory, the log1.txt file, prints the folder contents, and then deletes everything.
import java.nio.file.*;
import java.io.IOException;
public class MiniFileManager {
public static void main(String[] args) throws IOException {
Path logsDir = Paths.get("mydata/logs");
Files.createDirectories(logsDir);
Path logFile = logsDir.resolve("log1.txt");
Files.writeString(logFile, "Hello, log!");
System.out.println("Contents of folder " + logsDir + ":");
try (var stream = Files.list(logsDir)) {
stream.forEach(path -> System.out.println(" - " + path.getFileName()));
}
Files.deleteIfExists(logFile);
Files.deleteIfExists(logsDir);
System.out.println("File and folder deleted.");
}
}
Notes on the code:
- Files.createDirectories guarantees creation of the entire chain.
- resolve is a convenient way to append a file name to a path.
- Close the stream from Files.list via try-with-resources — especially critical on Windows.
5. Details and nuances
Checking for existence
Before creating/deleting, it’s useful to check whether the path exists:
if (!Files.exists(path)) {
Files.createDirectory(path);
}
Permissions
If the program lacks permissions to create/delete, you’ll get an AccessDeniedException. For example, creating a folder at the root of a disk as a regular user will almost always end in an error.
Empty vs. non-empty directory
You can delete only an empty directory (Files.delete). To delete with all contents, use recursive traversal (walkFileTree).
Cross-platform compatibility
The java.nio.file API works correctly on all popular OSes and accounts for path separators. To build paths, use Paths.get and Path.resolve rather than concatenating strings.
Symbolic links
You can ignore them for basic tasks, but if you encounter “unusual” entries that are neither a regular file nor a directory, they may be symlinks. We’ll return to them in advanced lectures.
6. Common mistakes when working with directories
Error #1: trying to delete a non-empty directory with a simple call to Files.delete(path). Java will throw a DirectoryNotEmptyException. Delete the contents first, then the folder itself.
Error #2: forgetting to close the stream from Files.list(). If you don’t use try-with-resources, the stream remains open, and on Windows you may get an error when deleting the folder.
Error #3: creating a directory without checking that the parent exists. Calling Files.createDirectory for a path like parent/child when parent doesn’t exist will lead to a NoSuchFileException. Use Files.createDirectories.
Error #4: using absolute paths without necessity. Prefer relative paths within the project — this makes the code more portable.
Error #5: not handling IOException. Any file system operation can fail. Wrap it in a try-catch or rethrow the exception.
Error #6: trying to create/delete in a folder without permissions. In this case, you’ll get an AccessDeniedException. Check the execution context and permissions.
GO TO FULL VERSION