1. Verzeichnisse erstellen
Ein Verzeichnis (auch Ordner) ist nicht nur ein Container für Dateien, sondern die Grundlage der Datenorganisation auf der Festplatte. In Anwendungen erstellen wir ständig Verzeichnisse für Eingabe-/Ausgabedaten, Logs, temporäre Dateien usw. Das moderne API java.nio.file macht das bequem und plattformübergreifend.
Schauen wir uns an, wie man mit den Klassen Files, Path und Paths Ordner erstellt, löscht und deren Inhalte anzeigt.
Files.createDirectory(path)
Erstellt ein Verzeichnis am angegebenen Pfad. Wenn das übergeordnete Verzeichnis fehlt, wird eine Ausnahme ausgelöst.
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("Verzeichnis erstellt: " + dir.toAbsolutePath());
} else {
System.out.println("Verzeichnis existiert bereits: " + dir.toAbsolutePath());
}
}
}
Wenn Sie versuchen, ein Verzeichnis zu erstellen, das bereits existiert, erhalten Sie eine FileAlreadyExistsException.
Files.createDirectories(path)
Erstellt die gesamte Verzeichnisstruktur. Falls eines der Zwischenverzeichnisse fehlt, wird es automatisch angelegt. Existiert ein Teil bereits, führt das nicht zu einem Fehler.
Path nestedDir = Paths.get("parent/child/grandchild");
Files.createDirectories(nestedDir);
System.out.println("Verzeichnisstruktur erstellt: " + nestedDir.toAbsolutePath());
Es ist, als würden Sie Java bitten, nicht nur das Haus zu bauen, sondern auch den Hauseingang und die Straße, falls es sie noch nicht gibt.
Typisches Beispiel: Wir erstellen eine Projektstruktur
Angenommen, Berichte sollen im Ordner output/reports/2024 gespeichert werden. Prüfen Sie nicht jedes Verzeichnis manuell – verwenden Sie createDirectories.
Path reportsPath = Paths.get("output/reports/2024");
Files.createDirectories(reportsPath);
Java ermittelt selbst, was bereits existiert und was erstellt werden muss.
2. Dateien und Verzeichnisse löschen
Files.delete(path)
Löscht eine Datei oder ein leeres Verzeichnis. Ist das Verzeichnis nicht leer, wird eine DirectoryNotEmptyException ausgelöst.
Path dir = Paths.get("testDir");
try {
Files.delete(dir);
System.out.println("Verzeichnis gelöscht: " + dir.toAbsolutePath());
} catch (DirectoryNotEmptyException e) {
System.out.println("Löschen nicht möglich: Verzeichnis ist nicht leer!");
}
Files.deleteIfExists(path)
Funktioniert wie delete, wirft jedoch keinen Fehler, wenn das Objekt nicht existiert. Gibt true zurück, wenn etwas gelöscht wurde, und false, wenn das Objekt nicht vorhanden war.
Path file = Paths.get("output/reports/2024/report.txt");
if (Files.deleteIfExists(file)) {
System.out.println("Datei gelöscht.");
} else {
System.out.println("Datei nicht gefunden, nichts gelöscht.");
}
Wie löscht man ein nicht leeres Verzeichnis?
Ein nicht leerer Ordner lässt sich nicht direkt löschen. Zuerst müssen Sie seinen gesamten Inhalt (Dateien und Unterverzeichnisse) entfernen und anschließend den Ordner selbst. Das geschieht rekursiv, z.B. über 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("Das Verzeichnis und sein gesamter Inhalt wurden gelöscht.");
}
}
}
Wenn Sie gerade erst anfangen, keine Sorge wegen dieses Codes – wir werden walkFileTree später ausführlicher behandeln.
3. Verzeichnisinhalt anzeigen
Files.list(path)
Gibt einen Stream<Path> zurück – einen Strom von Pfaden. Sie können den Ordnerinhalt über das Stream‑API verarbeiten. Jeder Eintrag ist eine Datei oder ein Unterverzeichnis (ohne Rekursion!).
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()));
}
}
Wichtiger Hinweis: Den Stream muss man unbedingt schließen, daher verwenden wir try‑with‑resources.
Beispiel: Dateinamen und Unterverzeichnisse ausgeben
Path reports2024 = Paths.get("output/reports/2024");
try (var stream = Files.list(reports2024)) {
stream.forEach(path -> {
String type = Files.isDirectory(path) ? "Verzeichnis" : "Datei";
System.out.println(path.getFileName() + " — " + type);
});
}
Dateiliste als Collection beziehen
List<Path> files = Files.list(reports2024)
.filter(Files::isRegularFile)
.toList();
System.out.println("Dateien im Verzeichnis:");
files.forEach(System.out::println);
Wichtig: Files.list(path) gibt nur den Inhalt des aktuellen Verzeichnisses (oberste Ebene) zurück. Für einen rekursiven Durchlauf verwenden Sie Files.walk(path).
4. Praxis: Mini‑Dateimanager
Das Tool erstellt das Verzeichnis mydata/logs, die Datei log1.txt, gibt den Ordnerinhalt aus und löscht anschließend alles.
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, "Hallo, Log!");
System.out.println("Inhalt des Verzeichnisses " + logsDir + ":");
try (var stream = Files.list(logsDir)) {
stream.forEach(path -> System.out.println(" - " + path.getFileName()));
}
Files.deleteIfExists(logFile);
Files.deleteIfExists(logsDir);
System.out.println("Datei und Verzeichnis wurden gelöscht.");
}
}
Anmerkungen zum Code:
- Files.createDirectories garantiert die Erstellung der gesamten Struktur.
- resolve – eine bequeme Möglichkeit, einen Dateinamen an einen Pfad anzuhängen.
- Den Stream von Files.list per try‑with‑resources schließen – unter Windows besonders wichtig.
5. Besonderheiten und Hinweise
Existenz prüfen
Vor dem Erstellen/Löschen ist es sinnvoll zu prüfen, ob der Pfad existiert:
if (!Files.exists(path)) {
Files.createDirectory(path);
}
Berechtigungen
Wenn das Programm keine Rechte zum Erstellen/Löschen hat, erhalten Sie eine AccessDeniedException. Zum Beispiel endet das Erstellen eines Ordners im Wurzelverzeichnis eines Laufwerks als normaler Benutzer fast immer mit einem Fehler.
Leeres vs. nicht leeres Verzeichnis
Löschen lässt sich nur ein leeres Verzeichnis (Files.delete). Für das Löschen mitsamt Inhalt verwenden Sie einen rekursiven Durchlauf (walkFileTree).
Plattformübergreifend
Das API java.nio.file funktioniert auf allen gängigen Betriebssystemen korrekt und berücksichtigt Pfadtrennzeichen. Zum Aufbau von Pfaden verwenden Sie Paths.get und Path.resolve, anstatt Strings zusammenzukleben.
Symbolische Links
Für grundlegende Aufgaben kann man sie ignorieren, aber wenn Sie auf „ungewöhnliche“ Einträge stoßen, die weder normale Datei noch Verzeichnis sind, handelt es sich möglicherweise um Symlinks. Darauf kommen wir in fortgeschrittenen Vorlesungen zurück.
6. Typische Fehler beim Arbeiten mit Verzeichnissen
Fehler Nr. 1: Versuch, ein nicht leeres Verzeichnis per Files.delete(path) zu löschen. Java wirft DirectoryNotEmptyException. Löschen Sie zuerst den Inhalt und anschließend den Ordner selbst.
Fehler Nr. 2: Den Stream aus Files.list() nicht geschlossen. Ohne try‑with‑resources bleibt der Stream offen, und unter Windows kann beim Löschen des Verzeichnisses ein Fehler auftreten.
Fehler Nr. 3: Ein Verzeichnis erstellen, ohne das Elternverzeichnis zu prüfen. Der Aufruf Files.createDirectory für einen Pfad wie parent/child, wenn parent nicht existiert, führt zu NoSuchFileException. Verwenden Sie Files.createDirectories.
Fehler Nr. 4: Unnötige Verwendung absoluter Pfade. Bevorzugen Sie relative Pfade innerhalb des Projekts – so wird der Code portabler.
Fehler Nr. 5: IOException wird nicht behandelt. Jeder Zugriff auf das Dateisystem kann fehlschlagen. Verpacken Sie ihn in try-catch oder werfen Sie die Ausnahme weiter.
Fehler Nr. 6: Versuch, in einem Ordner ohne Berechtigungen zu erstellen/zu löschen. In diesem Fall erhalten Sie eine AccessDeniedException. Prüfen Sie den Ausführungskontext und die Berechtigungen.
GO TO FULL VERSION