EMZETT.
Login

Files

Kurz: Java bietet mehrere APIs für Dateizugriff — von den klassischen java.io-Klassen (File, FileReader) bis zur moderneren java.nio.file.Files-Klasse.

Genauer: Die neuere java.nio.file-API (seit Java 7) bietet kompaktere, statische Methoden für gängige Operationen (Files.readAllLines(path), Files.write(...)) und bessere Fehlerbehandlung als die ältere java.io.File-Klasse. Alle Dateioperationen können scheitern (Datei existiert nicht, keine Berechtigung) und werfen deshalb geprüfte Exceptions.

Im Detail

Path pfad = Path.of("notizen.txt");
 
// Ganze Datei auf einmal lesen (nur für kleine/mittlere Dateien geeignet)
List<String> zeilen = Files.readAllLines(pfad);
String inhalt = Files.readString(pfad); // seit Java 11
 
// Ganze Datei auf einmal schreiben
Files.writeString(pfad, "Neuer Inhalt");
 
// Existenz und Eigenschaften prüfen, ohne die Datei zu öffnen
boolean existiert = Files.exists(pfad);
long groesse = Files.size(pfad);
boolean istVerzeichnis = Files.isDirectory(pfad);
 
// Über ein Verzeichnis iterieren
try (Stream<Path> dateien = Files.list(Path.of("."))) {
    dateien.filter(Files::isRegularFile).forEach(System.out::println);
}

Der Path-Typ selbst repräsentiert nur einen Dateipfad als Wert — er “öffnet” oder “prüft” nichts von sich aus, sondern dient als Argument für die statischen Methoden der Files-Klasse, die die eigentliche Arbeit übernehmen. Diese Trennung (Pfad als reiner Wert, Files als Werkzeugkasten mit Operationen darauf) ist bewusst so designt und ersetzt das ältere Modell, in dem eine einzelne File-Instanz sowohl den Pfad repräsentierte als auch Dutzende Instanzmethoden für Operationen darauf trug. Für sehr große Dateien, die nicht komplett in den Speicher passen, sind die zeilenweisen/stream-basierten Varianten (Files.lines(), BufferedReader) statt readAllLines()/readString() vorzuziehen.

Pfade zusammensetzen und normalisieren

Path bietet plattformunabhängige Methoden zum Zusammensetzen und Auflösen von Pfaden, statt Strings manuell mit / oder \ zu verketten (was auf Windows vs. Unix zu unterschiedlichen Ergebnissen führen würde):

Path basis = Path.of("projekt", "daten");
Path datei = basis.resolve("config.json"); // "projekt/daten/config.json" (OS-abhängiges Trennzeichen)
Path absolut = datei.toAbsolutePath();
Path eltern = datei.getParent(); // "projekt/daten"
String dateiname = datei.getFileName().toString(); // "config.json"
 
// Relative Pfade mit ".." werden korrekt aufgelöst
Path normalisiert = Path.of("a/b/../c").normalize(); // "a/c"

Verzeichnisse erstellen und kopieren

Files.createDirectories(Path.of("neu/verschachtelt/ordner")); // erstellt alle fehlenden Zwischenordner
Files.copy(Path.of("quelle.txt"), Path.of("ziel.txt"), StandardCopyOption.REPLACE_EXISTING);
Files.move(Path.of("alt.txt"), Path.of("neu.txt")); // umbenennen/verschieben

createDirectories() (Plural) legt bei Bedarf die gesamte fehlende Ordnerstruktur an, während createDirectory() (Singular) scheitert, wenn der übergeordnete Ordner noch nicht existiert — eine häufige Verwechslung, die zu einer unerwarteten NoSuchFileException führt.

Dateiattribute und Berechtigungen

Neben Inhalt und Existenz lassen sich auch Metadaten wie Änderungszeitpunkt und Berechtigungen über Files abfragen und setzen, ohne die Datei selbst zu öffnen:

FileTime zuletztGeaendert = Files.getLastModifiedTime(pfad);
boolean lesbar = Files.isReadable(pfad);
boolean schreibbar = Files.isWritable(pfad);
Files.setLastModifiedTime(pfad, FileTime.fromMillis(System.currentTimeMillis()));

Auf Unix-Systemen lassen sich zusätzlich POSIX-Dateiberechtigungen direkt setzen (Files.setPosixFilePermissions()) — unter Windows steht diese API zwar zur Verfügung, wirft aber eine UnsupportedOperationException, da Windows ein anderes Berechtigungsmodell nutzt.

Siehe auch: Create Files, Read Files, Write Files, Delete Files, I/O Streams