Dateien und Datenströme

**This is an old revision of the document!**

<!DOCTYPE markdown>

Dateien und Datenströme

Dateien

  • Speicherstrukturen für Daten
  • Herkunft des Wortes file
    • aus dem Altfranzösischen Wort “fil”, das “Faden” oder “Draht” bedeutete.
    • Im Mittelalter wurden Dokumente oft an einem Faden oder Draht befestigt, um sie zusammenzuhalten.
    • So entstand die Bedeutung des Wortes “file” als “Sammlung von Dokumenten”.
  • Im Deutschen: Datei = Daten + Kartei

Datenströme

  • kontinuierliche Datenflüsse von Quelle zu Ziel oder anders herum
  • Input / Output
  • Dateien “fließen” hinaus auf Datenträger und hinein in Arbeitsspeicher

Typen von Datenströmen

Byte-Streams

  • Folge von Bytes
  • Für Menschen nicht lesbar
  • Arbeiten mit InputStream und OutputStream und sind für Binärdaten wie Bilder oder Videos geeignet.

Text (Binär)-Streams

  • Folge von Zeichen (Unicode)
  • Arbeiten mit Reader und Writer, speziell für Textdaten in Unicode.

Java I/O-Grundlagen

import java.io.*
Die java.io-Bibliothek

  • für Ein- und Ausgabefunktionen verwendet werden
  • Daten lesen/schreiben aus/ in
    • Dateien
    • Konsole
    • Streams

Wichtigste Klassen in java.io

Byte-Streams

  • Verschiede InputStreams/ OutputStreams
  • Arbeiten byteweise
  • Beispiele: FileInputStream, FileOutputStream

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class StreamExample {
    public static void main(String[] args) {
        try (FileOutputStream fos = new FileOutputStream("binary.dat")) {
            fos.write(new byte[]{65, 66, 67}); // A, B, C
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        try (FileInputStream fis = new FileInputStream("binary.dat")) {
            int b;
            while ((b = fis.read()) != -1) {
                System.out.print((char) b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Text-Streams

  • Verschiedene Reader/Writer
  • Arbeiten mit Zeichen und unterstützen Encoding wie UTF-8 oder UTF-16
  • FileReader/ FileWriter
  • Lesen und Schreiben von Textdateien
    • Zeichen für Zeichen
  • BufferedReader/ BufferedWriter
    • Puffern Daten
    • Effizientere Verarbeitung von Textdateien

FileReader/ FileWriter

import java.io.FileReader;
import java.io.IOException;
 
public class FileReaderExample {
    public static void main(String[] args) {
        try (FileReader reader = new FileReader("example.txt")) {
            int ch;
            while ((ch = reader.read()) != -1) { // Zeichenweise lesen
                System.out.print((char) ch);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

FileReader/ FileWriter

import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
 
public class FileReaderWriterExample {
    public static void main(String[] args) {
        try (FileWriter writer = new FileWriter("example.txt")) {
            writer.write("Hallo, Java IO!");
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        try (FileReader reader = new FileReader("example.txt")) {
            int ch;
            while ((ch = reader.read()) != -1) {
                System.out.print((char) ch);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


BufferedReader/ BufferedWriter

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
 
public class BufferedReaderExample {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) { // Zeilenweise lesen
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BufferedReader/ BufferedWriter

import java.io.*;
 
public class BufferedReaderWriterExample {
    public static void main(String[] args) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("example.txt"))) {
            writer.write("Effizientes Schreiben mit BufferedWriter!");
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


Wann verwende ich was

  • FileReader
    • kleinere Dateien
    • Bei Notwendigkeit von zeichenweisem Einlesen
  • BufferedReader
    • effizientes Lesen von Textdaten.
  • Best Practices:
    • try-with-resources: Automatisches Schließen von Streams, um Ressourcenlecks zu vermeiden.
    • Fehlerbehandlung: Abfangen von IOException für robusteren Code.

Datei neu erstellen vs. Daten an bestehende Datei anhängen

...
    public static void main(String[] args) {
        String filePath = "example.txt";
 
        // Schreiben in die Datei (überschreibt den bestehenden Inhalt)
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
            writer.write("Dies ist der erste Text in der Datei.");
            writer.newLine(); // Neue Zeile einfügen
            writer.write("Noch eine Zeile wird hinzugefügt.");
            System.out.println("Text erfolgreich geschrieben.");
        } catch (IOException e) {
            System.out.println("Fehler beim Schreiben in die Datei: " + e.getMessage());
        }
 
        // Anhängen an die Datei
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
            writer.newLine(); // Neue Zeile am Ende der Datei
            writer.write("Dies ist ein angehängter Text.");
            writer.newLine(); // Neue Zeile einfügen
            writer.write("Noch ein angehängter Text.");
            System.out.println("Text erfolgreich angehängt.");
        } catch (IOException e) {
            System.out.println("Fehler beim Anhängen an die Datei: " + e.getMessage());
        }
    }
...
---
## What about Scanner?
- Hauptsächliche Verwendung
- Nicht nur Dateien lesen kann, sondern auch 
- Parsen von Eingaben bietet
- flexibler, aber oft weniger performant bei großen Datenmengen geht
 
---
 
### Vergleich: Scanner vs BufferedReader vs FileReader
 
| **Kriterium**              | **FileReader**                                 | **BufferedReader**                              | **Scanner**                                      |
|-----------------------------|-----------------------------------------------|-----------------------------------------------|------------------------------------------------|
| **Hauptzweck**             | Zeichenweise aus Dateien lesen.               | Effizientes Lesen von Zeichen und Zeilen.      | Lesen und **Parsen** von Eingaben, z. B. Zahlen oder Strings. |
| **Lesemethoden**           | `read()` (Zeichenweise).                      | `readLine()` (Zeilenweise) oder `read()`.      | Methoden wie `nextInt()`, `nextLine()`, `next()`. |
| **Performance**            | Langsam für große Dateien.                    | Schnell für große Dateien.                    | Langsamer bei großen Datenmengen (Parsing braucht Zeit). |
 
---
 
 
### Wann sollte man welchen verwenden?
 
- `Scanner`
  - Parsing
  - Anwendungen, bei denen unterschiedliche Datentypen aus der Eingabe verarbeitet werden sollen.  
- `BufferedReader`
  - schneller
  - Zeilenweise Textverarbeitung
  - ohne Dateninterpretation
- `FileReader`
  - einfachste Variante
  - wird wegen fehlender Effizienz und Flexibilität seltener verwendet