EMZETT.
Login

Kurz: Das Paket java.nio.file (NIO.2) ist der moderne Weg, mit Dateien zu arbeiten: Path beschreibt einen Pfad, Files erledigt die Arbeit.

Teil des Kurses Java

Kapitel 17 von 22 im Kurs Java. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Das Paket java.nio.file (NIO.2) ist der moderne Weg, mit Dateien zu arbeiten: Path beschreibt einen Pfad, Files erledigt die Arbeit.

import java.io.IOException;
import java.nio.file.*;
import java.util.*;
 
public class Dateien {
    public static void main(String[] args) throws IOException {
        Path ordner = Files.createTempDirectory("kurs");
        Path datei = ordner.resolve("notiz.txt");               // Pfad zusammensetzen
 
        Files.writeString(datei, "Zeile 1\nZeile 2\n");
        Files.writeString(datei, "Zeile 3\n", StandardOpenOption.APPEND);
 
        String inhalt = Files.readString(datei);
        List<String> zeilen = Files.readAllLines(datei);
        System.out.println(zeilen + " " + inhalt.length());
        System.out.println(Files.exists(datei) + " " + Files.size(datei) + " " + datei.getFileName());
 
        Path kopie = ordner.resolve("kopie.txt");
        Files.copy(datei, kopie);
        try (var strom = Files.list(ordner)) {
            strom.map(p -> p.getFileName().toString()).sorted().forEach(System.out::println);
        }
        Files.delete(kopie);
        Files.delete(datei);
        Files.delete(ordner);
        System.out.println(Files.exists(ordner));
    }
}

Ausgabe:

[Zeile 1, Zeile 2, Zeile 3] 24
true 24 notiz.txt
kopie.txt
notiz.txt
false

Alle Methoden können eine IOException werfen. Schreibe throws IOException oder fange sie.

Zeilenweise lesen

Große Dateien liest man nicht komplett, sondern Zeile für Zeile:

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
 
public class Zeilen {
    public static void main(String[] args) throws IOException {
        Path p = Files.createTempFile("daten", ".txt");
        Files.write(p, java.util.List.of("Mia;17", "Tom;19", "Zoe;21"), StandardCharsets.UTF_8);
 
        try (BufferedReader r = Files.newBufferedReader(p)) {
            String zeile;
            int summe = 0;
            while ((zeile = r.readLine()) != null) {
                String[] teile = zeile.split(";");
                summe += Integer.parseInt(teile[1]);
            }
            System.out.println("Summe der Alter: " + summe);
        }
        try (var stream = Files.lines(p)) {                      // als Stream
            System.out.println(stream.filter(z -> z.contains("o")).count());
        }
        try (BufferedWriter w = Files.newBufferedWriter(p)) {
            w.write("neu");
            w.newLine();
        }
        System.out.println(Files.readString(p).trim());
        Files.delete(p);
    }
}

Ausgabe:

Summe der Alter: 57
2
neu

Gib den Zeichensatz an (StandardCharsets.UTF_8), wenn Umlaute vorkommen.

Pfade

import java.nio.file.*;
 
public class Pfade {
    public static void main(String[] args) {
        Path p = Path.of("ordner", "unter", "bild.png");
        System.out.println(p + " " + p.getFileName() + " " + p.getParent() + " " + p.getNameCount());
        System.out.println(Path.of("/a/b/../c/./d").normalize());
        System.out.println(Path.of("/a/b").relativize(Path.of("/a/b/c/d")));
        System.out.println(p.toString().endsWith(".png") + " " + p.isAbsolute());
    }
}

Ausgabe:

ordner/unter/bild.png bild.png ordner/unter 3
/a/c/d
c/d
true false

Ordner durchlaufen

import java.io.IOException;
import java.nio.file.*;
import java.util.stream.*;
 
public class Baum {
    public static void main(String[] args) throws IOException {
        Path wurzel = Files.createTempDirectory("baum");
        Files.createDirectories(wurzel.resolve("a/b"));
        Files.writeString(wurzel.resolve("a/eins.txt"), "1");
        Files.writeString(wurzel.resolve("a/b/zwei.txt"), "22");
        try (Stream<Path> s = Files.walk(wurzel)) {
            s.filter(Files::isRegularFile)
             .map(p -> wurzel.relativize(p).toString())
             .sorted()
             .forEach(System.out::println);
        }
        try (Stream<Path> s = Files.walk(wurzel)) {                 // aufräumen: tiefste zuerst
            s.sorted(java.util.Comparator.reverseOrder()).forEach(p -> p.toFile().delete());
        }
        System.out.println(Files.exists(wurzel));
    }
}

Ausgabe:

a/b/zwei.txt
a/eins.txt
false

Eingabe von der Tastatur

Mit Scanner liest du Eingaben. Er funktioniert auch mit Texten statt Tastatur:

import java.util.Scanner;
 
public class Eingabe {
    public static void main(String[] args) {
        Scanner sc = new Scanner("Mia 17\n3.5\nein ganzer Satz\n");     // statt System.in
        String name = sc.next();
        int alter = sc.nextInt();
        double zahl = sc.nextDouble();
        sc.nextLine();                                     // Rest der Zeile verwerfen
        String satz = sc.nextLine();
        System.out.println(name + " " + alter + " " + zahl + " | " + satz);
        System.out.println(sc.hasNextLine());
    }
}

Ausgabe:

Mia 17 3.5 | ein ganzer Satz
false

Im echten Programm: new Scanner(System.in). Nach nextInt() bleibt der Zeilenumbruch stehen, deshalb braucht man ein zusätzliches nextLine() vor dem Lesen einer ganzen Zeile.

Serialisierung: JSON

Java hat kein eingebautes JSON. Üblich sind die Bibliotheken Jackson oder Gson:

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(new Person("Mia", 17));      // {"name":"Mia","alter":17}
Person p = mapper.readValue(json, Person.class);

Merke

  • Modern: Path und Files (readString, writeString, readAllLines, lines, walk)
  • Dateioperationen werfen IOException (checked)
  • Große Dateien zeilenweise lesen (BufferedReader, Files.lines), Ressourcen mit try-with-resources schließen
  • Path.of(...), resolve, normalize statt Zeichenketten für Pfade
  • Scanner liest Eingaben; für JSON Jackson oder Gson

Übungsaufgabe

Schreibe ein Programm, das eine Textdatei einliest, Wörter zählt und das Ergebnis in eine zweite Datei schreibt.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Lambdas und Streams

Weiter: Datum und Zeit

Alle Kapitel: Java im Überblick