Delete a File
Deleting a file sounds simple, but Java gives you a few different tools to do it — each with slightly different behavior around missing files, non-empty directories, and error reporting. Knowing which one to reach for will save you from silent failures and unexpected exceptions.
Using File.delete() (Classic API)
The oldest approach uses java.io.File. Call delete() on a File object pointing to the path you want to remove. It returns true if the deletion succeeded and false otherwise — no exception is thrown on failure.
import java.io.File;
public class DeleteFileExample {
public static void main(String[] args) {
File file = new File("notes.txt");
if (file.delete()) {
System.out.println("Deleted: " + file.getAbsolutePath());
} else {
System.out.println("Failed to delete. Does the file exist?");
}
}
}
Output (when file exists):
Deleted: /home/user/projects/notes.txt
Output (when file is missing):
Failed to delete. Does the file exist?
Warning:
File.delete()returnsfalsesilently for many reasons — the file is missing, a directory is non-empty, or the process lacks permission. You get no details about why it failed. For robust code, prefer the NIO.2 approach below.
Checking Existence First
A common defensive pattern with the classic API:
import java.io.File;
public class SafeDelete {
public static void main(String[] args) {
File file = new File("temp.log");
if (file.exists()) {
boolean deleted = file.delete();
System.out.println(deleted ? "Deleted." : "Could not delete.");
} else {
System.out.println("File does not exist — nothing to do.");
}
}
}
Note: There is a tiny race window between
exists()anddelete(). Another process could remove the file in between, causingdelete()to returnfalseanyway. The NIO.2 API handles this more cleanly.
Using Files.delete() (NIO.2, Java 7+)
java.nio.file.Files.delete() is the modern preferred approach. Unlike File.delete(), it throws an exception when deletion fails, giving you a clear reason:
NoSuchFileException— the file does not existDirectoryNotEmptyException— you tried to delete a non-empty directoryIOException— permission denied or other OS-level error
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
public class NioDeleteFile {
public static void main(String[] args) {
Path path = Paths.get("report.txt");
try {
Files.delete(path);
System.out.println("Deleted: " + path.toAbsolutePath());
} catch (NoSuchFileException e) {
System.out.println("File not found: " + e.getFile());
} catch (IOException e) {
System.err.println("Deletion failed: " + e.getMessage());
}
}
}
Output:
Deleted: /home/user/projects/report.txt
Tip: In Java 11+ you can write
Path.of("report.txt")instead ofPaths.get("report.txt")— shorter and just as clear.
Using Files.deleteIfExists() (NIO.2, Java 7+)
When you simply want to remove a file if it is there and do nothing if it is not, Files.deleteIfExists() is the cleanest option. It returns true if the file was deleted and false if it was not there — without throwing NoSuchFileException.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class DeleteIfExistsExample {
public static void main(String[] args) {
Path path = Paths.get("cache.tmp");
try {
boolean deleted = Files.deleteIfExists(path);
System.out.println(deleted ? "Cache file removed." : "No cache file found.");
} catch (IOException e) {
System.err.println("Error during deletion: " + e.getMessage());
}
}
}
Output (file present):
Cache file removed.
Output (file absent):
No cache file found.
This is especially useful in cleanup and teardown code where you are not sure whether the file was ever created.
Deleting an Empty Directory
Both File.delete() and Files.delete() can remove a directory, but only if it is empty. The behavior mirrors the OS rmdir command.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class DeleteEmptyDir {
public static void main(String[] args) throws IOException {
Path dir = Paths.get("temp-dir");
Files.createDirectory(dir); // create it first for demo
Files.delete(dir);
System.out.println("Empty directory deleted.");
}
}
If the directory still contains files, Files.delete() throws DirectoryNotEmptyException — the OS will not let you delete a directory that has contents.
Deleting a Non-Empty Directory (Recursive Delete)
Java has no single built-in call to recursively delete a directory tree (like rm -rf). You need to walk the tree yourself. The cleanest way uses Files.walk() combined with a sorted, reversed stream so that children are deleted before parents.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
public class RecursiveDelete {
public static void deleteDirectory(Path root) throws IOException {
Files.walk(root)
.sorted(Comparator.reverseOrder()) // deepest entries first
.forEach(path -> {
try {
Files.delete(path);
} catch (IOException e) {
throw new RuntimeException("Failed to delete: " + path, e);
}
});
}
public static void main(String[] args) throws IOException {
Path dir = Paths.get("my-temp-folder");
// create demo structure
Files.createDirectories(dir.resolve("sub"));
Files.createFile(dir.resolve("sub/data.txt"));
deleteDirectory(dir);
System.out.println("Directory tree deleted.");
}
}
Output:
Directory tree deleted.
Warning: There is no “recycle bin” when deleting with Java — files are gone immediately and permanently. Always double-check the path before recursively deleting a directory tree.
Files.walk() returns a lazy Stream<Path>, so it does not load all paths into memory at once. This is safe for deep or large directory trees. See the Stream API page for more on lazy streams.
Comparison Table
| Method | Throws on missing file? | Throws on failure? | Works on dirs? | Since |
|---|---|---|---|---|
File.delete() | No (returns false) | No (returns false) | Yes (empty only) | Java 1.0 |
Files.delete() | Yes (NoSuchFileException) | Yes (IOException) | Yes (empty only) | Java 7 |
Files.deleteIfExists() | No (returns false) | Yes (IOException) | Yes (empty only) | Java 7 |
For new code, prefer Files.delete() or Files.deleteIfExists() from the NIO.2 API. They give you real exception details when things go wrong.
Under the Hood
When you call Files.delete(), the JVM maps it to a native OS system call — unlink() for files on POSIX systems (Linux, macOS) and DeleteFileW on Windows.
The key insight: unlink() does not immediately destroy file data. It removes the directory entry (the filename-to-inode mapping) and decrements the inode’s hard link count. The actual disk blocks are only freed once the link count drops to zero and no process has the file open. This means:
- If another thread or process has the file open when you delete it, that process can still read and write through its open file descriptor until it closes the handle.
- On Linux you can even delete a file you currently have open in your own process — the data persists until your file descriptor is closed.
- On Windows,
DeleteFileWtypically fails withAccessDeniedExceptionif any process has the file open, because Windows holds an exclusive lock on open files by default.
For directories, the OS enforces that the directory inode has no child entries before allowing removal. That is why non-empty directory deletion fails at the OS level — Java simply surfaces that error.
If you need soft-deletion patterns (move to a trash folder), atomic replacement, or watching for deletion events, explore Files.move() and the WatchService API in NIO.2.
Related Topics
- File Class — the
Fileobject that underpins classic file and directory operations - Create a File — how to create files before (or instead of) deleting them
- NIO.2: Path & Files — the full modern NIO.2 API for filesystem operations
- Write to a File — writing content to files you manage
- Read a File Line by Line — reading back data from files
- Stream API — understanding the lazy
Files.walk()stream used in recursive deletion