1. Wiederholung: File vs Path vs Files
Der gute alte File
Ja... In Java-Projekten gibt es reichlich Legacy-Code. Deshalb erinnern wir uns noch einmal an den Java‑Veteranen, die Klasse File. Sie existiert seit der ersten Sprachversion und ermöglicht die Arbeit mit Dateien und Ordnern: prüfen, ob eine Datei existiert, ihren Namen, ihre Größe, das Änderungsdatum abrufen, Dateien und Ordner erstellen und löschen. Wie wir bereits wissen, hat sie zahlreiche Schwächen: Ein Teil der Methoden verhält sich nicht intuitiv, nicht alle Operationen sind plattformübergreifend unterstützt, und manche Methoden liefern statt Ausnahmen einfach false zurück (was für das Debuggen nicht immer praktisch ist).
import java.io.File;
File file = new File("example.txt");
System.out.println("Existiert die Datei? " + file.exists());
System.out.println("Ist das eine Datei? " + file.isFile());
System.out.println("Ist das ein Verzeichnis? " + file.isDirectory());
Path und Files: moderner Ansatz (Java 7+)
Mit Java 7 erschien das Paket java.nio.file, das leistungsfähigere und flexiblere Werkzeuge bietet. Zwei Hauptakteure:
- Path – ein Interface, das einen Pfad zu einer Datei oder zu einem Verzeichnis beschreibt. Man könnte sagen, es ist eine „intelligente Zeichenkette“: kann Pfade zerlegen, zusammenfügen, analysieren und vergleichen.
- Files – eine Utility-Klasse mit vielen statischen Methoden zur Arbeit mit Dateien und Verzeichnissen: Erstellen, Löschen, Kopieren, Lesen, Schreiben, Informationen abrufen.
import java.nio.file.Path;
import java.nio.file.Paths;
Path path = Paths.get("example.txt");
System.out.println("Pfad: " + path);
Fun Fact: Die Klasse Path ist nicht einfach nur ein String! Sie kennt die Verzeichnis-Trenner, kann relative und absolute Pfade analysieren und funktioniert unter Windows und Linux gleichermaßen gut.
Vergleichstabelle: File und Path/Files
| Kriterium | File (alter API) | Path + Files (moderner API) |
|---|---|---|
| Syntax | OOP‑Stil | Kombination aus Path + statischen Methoden von Files |
| Plattformunabhängigkeit | Teilweise | Ausgezeichnet, berücksichtigt das Betriebssystem |
| Ausnahmen | Nicht immer | Fast immer |
| Neue Möglichkeiten | Nein | Ja (Attribute, Berechtigungen, Links u. a.) |
| Empfohlen | Eher nicht | Ja |
2. Informationen über Datei/Verzeichnis abrufen
Schauen wir uns an, wie man das Wichtigste über eine Datei oder ein Verzeichnis herausfindet: ob das Objekt existiert, sein Typ (Datei oder Verzeichnis), Größe, Name, Pfad und das übergeordnete Verzeichnis.
Existenz prüfen
Über File
File file = new File("example.txt");
if (file.exists()) {
System.out.println("Die Datei existiert!");
} else {
System.out.println("Datei nicht gefunden.");
}
Über Path und Files
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
Path path = Paths.get("example.txt");
if (Files.exists(path)) {
System.out.println("Die Datei existiert!");
} else {
System.out.println("Datei nicht gefunden.");
}
Tipp: Für neue Projekte verwenden Sie immer Path und Files. Das ist sicherer, komfortabler und plattformübergreifend.
Typ prüfen: Datei oder Verzeichnis
File
if (file.isFile()) {
System.out.println("Das ist eine Datei.");
} else if (file.isDirectory()) {
System.out.println("Das ist ein Verzeichnis.");
}
Path + Files
if (Files.isRegularFile(path)) {
System.out.println("Das ist eine Datei.");
} else if (Files.isDirectory(path)) {
System.out.println("Das ist ein Verzeichnis.");
}
Dateigröße ermitteln
File
long size = file.length();
System.out.println("Dateigröße: " + size + " Byte");
Path + Files
try {
long size = Files.size(path);
System.out.println("Dateigröße: " + size + " Byte");
} catch (IOException e) {
System.out.println("Fehler beim Ermitteln der Dateigröße: " + e.getMessage());
}
Achtung: Für ein Verzeichnis gibt die Methode length() immer 0 zurück, und Files.size(path) löst eine IOException aus. Die Größe eines Verzeichnisses ist die Summe der Größen aller darin enthaltenen Dateien (mehr dazu in den nächsten Vorlesungen).
Absoluten und relativen Pfad abrufen
File
System.out.println("Relativer Pfad: " + file.getPath());
System.out.println("Absoluter Pfad: " + file.getAbsolutePath());
Path
System.out.println("Relativer Pfad: " + path);
System.out.println("Absoluter Pfad: " + path.toAbsolutePath());
Dateiname und übergeordnetes Verzeichnis abrufen
File
System.out.println("Dateiname: " + file.getName());
System.out.println("Übergeordnetes Verzeichnis: " + file.getParent());
Path
System.out.println("Dateiname: " + path.getFileName());
System.out.println("Übergeordnetes Verzeichnis: " + path.getParent());
Praxis-Tipp: Path kann nicht nur mit Dateien, sondern auch mit Verzeichnissen, mit relativen und absoluten Pfaden arbeiten und zerlegt einen Pfad zudem leicht in seine Teile.
3. Dateiattribute abrufen
Manchmal möchte man nicht nur Größe und Name wissen, sondern auch etwas Interessanteres: Erstellungsdatum, letztes Änderungsdatum, Zugriffsrechte.
Erstellungsdatum, letztes Änderungsdatum
File (eingeschränkt)
long lastModified = file.lastModified();
System.out.println("Letztes Änderungsdatum: " + new java.util.Date(lastModified));
Nachteil: Das Erstellungsdatum einer Datei lässt sich über File nicht ermitteln!
Path + Files
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
try {
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
FileTime creationTime = attrs.creationTime();
FileTime lastModifiedTime = attrs.lastModifiedTime();
System.out.println("Erstellungsdatum: " + creationTime);
System.out.println("Letztes Änderungsdatum: " + lastModifiedTime);
} catch (IOException e) {
System.out.println("Fehler beim Abrufen von Attributen: " + e.getMessage());
}
Zugriffsrechte prüfen
File
System.out.println("Lesbar? " + file.canRead());
System.out.println("Schreibbar? " + file.canWrite());
System.out.println("Ausführbar? " + file.canExecute());
Path + Files
System.out.println("Lesbar? " + Files.isReadable(path));
System.out.println("Schreibbar? " + Files.isWritable(path));
System.out.println("Ausführbar? " + Files.isExecutable(path));
Fun Fact: Unter Windows sind die Zugriffsrechte begrenzter, während man unter Unix-Systemen deutlich mehr Rechte abfragen und ändern kann (z. B. über POSIX-Attribute).
4. Typische Fehler beim Abrufen von Dateiinformationen
Fehler Nr. 1: File verwenden, obwohl Path nötig ist.
Viele Einsteiger verwenden weiterhin File, weil es einfacher ist oder „weil es überall im Internet so steht“. Mit Path und Files kann man dasselbe tun – nur zuverlässiger und moderner.
Fehler Nr. 2: Den Objekttyp nur über File prüfen.
Wenn Sie nur file.isFile() und file.isDirectory() verwenden, können Ihnen „besondere“ Dateien entgehen (symbolische Links, Geräte). Im modernen API gibt es Files.isRegularFile(path), Files.isDirectory(path) und weitere Prüfungen.
Fehler Nr. 3: Ausnahmen ignorieren.
Die Methoden Files.size(path) und Files.readAttributes(...) werfen IOException. Wenn Sie Ausnahmen nicht behandeln, stürzt das Programm beim ersten Zugriffsfehler ab oder wenn die Datei während der Ausführung verschwindet.
Fehler Nr. 4: Erwarten, dass sich die Ordnergröße direkt ermitteln lässt.
Die Methode Files.size(path) löst für ein Verzeichnis eine Ausnahme aus. Um die Größe eines Verzeichnisses zu ermitteln, muss man die Größen aller enthaltenen Dateien rekursiv aufsummieren.
Fehler Nr. 5: Unzureichende Prüfung der Zugriffsrechte.
Selbst wenn die Datei existiert, haben Sie möglicherweise keine Lese- bzw. Schreibrechte. Prüfen Sie vor Operationen stets die Rechte: Files.isReadable(path), Files.isWritable(path), Files.isExecutable(path).
GO TO FULL VERSION