Delete Files
Kurz: Eine Datei vom Dateisystem entfernen — z. B. mit File.delete() (gibt boolean zurück) oder Files.delete(path) (wirft eine Exception bei Fehlschlag).
Genauer: delete() scheitert stillschweigend (liefert nur false), wenn z. B. die Datei noch von einem offenen Stream gesperrt ist — ein häufiger Grund für “das Löschen hat nicht geklappt, aber ich weiß nicht warum”. Files.deleteIfExists(path) ist die sichere Variante, wenn nicht garantiert ist, dass die Datei überhaupt existiert.
Im Detail
File alteDatei = new File("temp.txt");
boolean geloescht = alteDatei.delete(); // false bei Fehlschlag, keine Exception, kein Grund
// Moderne API - unterscheidet klar zwischen den Fällen
try {
Files.delete(Path.of("temp2.txt")); // wirft NoSuchFileException, falls nicht vorhanden
} catch (NoSuchFileException e) {
System.out.println("Datei existierte nicht");
} catch (IOException e) {
System.err.println("Löschen fehlgeschlagen: " + e.getMessage());
}
// Sicherste Variante, wenn Existenz unklar ist
boolean warVorhanden = Files.deleteIfExists(Path.of("temp3.txt"));Ein Grund, warum delete()/Files.delete() scheitern kann, obwohl die Datei existiert: unter Windows verweigert das Betriebssystem das Löschen, solange noch ein Programm (auch das eigene, über einen nicht geschlossenen Stream) einen offenen Dateihandle darauf hält — ein Klassiker ist ein vergessenes close() bzw. fehlendes try-with-resources weiter oben im Code, das die Datei “blockiert” hält.
Verzeichnisse löschen
Sowohl File.delete() als auch Files.delete() löschen ein Verzeichnis nur, wenn es LEER ist — bei einem nicht-leeren Verzeichnis scheitern beide (bei File still mit false, bei Files mit DirectoryNotEmptyException). Um einen ganzen Verzeichnisbaum rekursiv zu löschen, gibt es in der Standardbibliothek keine eingebaute Ein-Zeiler-Methode — üblich ist, den Baum mit Files.walk() von den Blättern zur Wurzel zu durchlaufen und jede Datei/jeden Ordner einzeln zu löschen:
try (Stream<Path> pfade = Files.walk(Path.of("altesVerzeichnis"))) {
pfade.sorted(Comparator.reverseOrder()) // tiefste Einträge zuerst
.forEach(pfad -> {
try {
Files.delete(pfad);
} catch (IOException e) {
System.err.println("Konnte nicht löschen: " + pfad);
}
});
}Die Sortierung mit Comparator.reverseOrder() ist entscheidend: Files.walk() liefert Einträge standardmäßig von der Wurzel zu den Blättern (Ordner vor Inhalt), aber ein Ordner lässt sich erst löschen, wenn er leer ist — die umgekehrte Reihenfolge stellt sicher, dass Dateien vor ihren übergeordneten Ordnern gelöscht werden.
deleteOnExit()
File.deleteOnExit() markiert eine Datei zum automatischen Löschen, sobald die JVM sauber beendet wird — praktisch für temporäre Dateien, birgt aber zwei Fallstricke: Die Markierung lässt sich nicht rückgängig machen, und bei einem abrupten JVM-Absturz (z. B. kill -9) wird sie gar nicht erst ausgeführt. Für kurzlebige temporäre Dateien innerhalb einer einzelnen Methode ist Files.createTempFile() in Kombination mit try-with-resources oft die robustere Wahl.
Sicherheitsaspekt: Löschen vor Prüfung
Ein subtiler Fehler ist, Existenz und Löschung in zwei getrennten Schritten zu prüfen (if (Files.exists(pfad)) Files.delete(pfad);) — zwischen den beiden Aufrufen kann theoretisch ein anderer Prozess die Datei bereits gelöscht oder verändert haben (Race Condition). Files.deleteIfExists() führt beide Schritte atomar aus und vermeidet dieses Zeitfenster.
Siehe auch: Files, Exceptions, try-with-resources