Delete Files
In short: Removing a file from the file system — e.g. with File.delete() (returns a boolean) or Files.delete(path) (throws an exception on failure).
In more detail: delete() fails silently (only returns false) if, for example, the file is still locked by an open stream — a common cause of “the delete didn’t work, but I don’t know why”. Files.deleteIfExists(path) is the safe variant when it’s not guaranteed the file even exists.
In Depth
File oldFile = new File("temp.txt");
boolean deleted = oldFile.delete(); // false on failure, no exception, no reason given
// Modern API - clearly distinguishes between cases
try {
Files.delete(Path.of("temp2.txt")); // throws NoSuchFileException if not present
} catch (NoSuchFileException e) {
System.out.println("File did not exist");
} catch (IOException e) {
System.err.println("Delete failed: " + e.getMessage());
}
// Safest variant when existence is unclear
boolean wasPresent = Files.deleteIfExists(Path.of("temp3.txt"));One reason delete()/Files.delete() can fail even though the file exists: on Windows, the operating system refuses the delete as long as any program (even your own, via a stream that wasn’t closed) holds an open file handle on it — a classic culprit is a forgotten close() or missing try-with-resources earlier in the code, which keeps the file “locked”.
Deleting directories
Both File.delete() and Files.delete() only delete a directory if it’s EMPTY — for a non-empty directory, both fail (silently with false for File, with DirectoryNotEmptyException for Files). To recursively delete an entire directory tree, there’s no built-in one-liner method in the standard library — the usual approach is to walk the tree with Files.walk() from the leaves to the root and delete each file/folder individually:
try (Stream<Path> paths = Files.walk(Path.of("oldDirectory"))) {
paths.sorted(Comparator.reverseOrder()) // deepest entries first
.forEach(path -> {
try {
Files.delete(path);
} catch (IOException e) {
System.err.println("Could not delete: " + path);
}
});
}The sorting with Comparator.reverseOrder() is crucial: Files.walk() returns entries from root to leaves by default (folder before content), but a folder can only be deleted once it’s empty — the reverse order ensures files are deleted before their parent folders.
deleteOnExit()
File.deleteOnExit() marks a file for automatic deletion once the JVM shuts down cleanly — useful for temporary files, but has two pitfalls: the marking can’t be undone, and on an abrupt JVM crash (e.g. kill -9) it doesn’t run at all. For short-lived temporary files within a single method, Files.createTempFile() combined with try-with-resources is often the more robust choice.
Security aspect: delete after check
A subtle bug is checking existence and deletion in two separate steps (if (Files.exists(path)) Files.delete(path);) — between the two calls, another process could theoretically have already deleted or changed the file (a race condition). Files.deleteIfExists() performs both steps atomically and avoids this time window.
See also: Files, Exceptions, try-with-resources