Assignment Chef icon Assignment Chef
All German tutorials

Programming lesson

Scanner und CSVParser in Java: Schritt-für-Schritt-Anleitung für ECS140A

Lerne, wie du einen eigenen Scanner und CSVParser in Java implementierst – basierend auf den Anforderungen der ECS140A Projekte 1–4. Mit praktischen Beispielen und Tipps für den CSIF.

Scanner Java CSVParser Java ECS140A Projekt 1 PeekableCharacterStream Tokenisierung Java CSV parsen Java Java Scanner Tutorial Programmiersprachen Scanner CSV Parser Implementierung Java FileInputStream Token-Regeln Java CSIF Java Projekt ECS140A Lösung Java Parser Beispiel CSV Header Map Java

Einleitung: Warum Scanner und CSVParser wichtig sind

In der Programmiersprachenverarbeitung sind Scanner und Parser grundlegende Werkzeuge. Ein Scanner zerlegt einen Zeichenstrom in Tokens, die dann von einem Parser weiterverarbeitet werden. In diesem Tutorial zeige ich dir, wie du für die ECS140A Projekte 1–4 einen eigenen Scanner und einen CSVParser in Java implementierst. Diese Konzepte sind nicht nur für dein Studium relevant, sondern auch in der Praxis – etwa beim Parsen von Konfigurationsdateien oder beim Verarbeiten von CSV-Daten aus Umfragen.

Aktuell (Juni 2026) sind CSV-Dateien immer noch das Standardformat für Datenaustausch in vielen Bereichen, von der Finanzanalyse bis zu KI-Trainingsdaten. Ein solider Parser ist daher eine wertvolle Fähigkeit.

Projektübersicht: Was du implementieren wirst

Deine Aufgaben umfassen:

  • PeekableCharacterStream: Eine Klasse, die einen FileInputStream kapselt und Methoden zum Vorausschauen und Lesen von Zeichen bietet.
  • Scanner: Zerlegt den Zeichenstrom in Tokens gemäß den vorgegebenen Token-Regeln.
  • CSVParser: Parst CSV-Dateien mit Header-Zeile und gibt jede Zeile als Map zurück.

Alle Klassen müssen auf dem CSIF (Computer Science Instructional Facility) kompilieren und laufen. Du wirst eine Makefile und eine README.txt einreichen.

Schritt 1: PeekableCharacterStream implementieren

Die Schnittstelle PeekableCharacterStream erlaubt es, Zeichen vorauszuschauen, ohne sie zu konsumieren. Das ist essentiell für den Scanner, um Tokens korrekt zu erkennen.

Wichtige Methoden

  • moreAvailable(): Gibt true zurück, wenn noch Zeichen vorhanden sind.
  • peekNextChar(): Gibt das nächste Zeichen zurück, ohne es zu entfernen.
  • peekAheadChar(int ahead): Gibt das Zeichen an Position ahead zurück (0 = nächstes).
  • getNextChar(): Gibt das nächste Zeichen zurück und entfernt es.
  • close(): Schließt den Stream.

Implementiere eine Klasse FilePeekableCharacterStream, die einen FileInputStream verwendet. Verwende einen Puffer (z.B. ArrayList<Integer>), um die vorausgeschauten Zeichen zu speichern. Achte darauf, dass -1 für das Ende des Streams steht.

public class FilePeekableCharacterStream implements PeekableCharacterStream {
    private FileInputStream fis;
    private List<Integer> buffer = new ArrayList<>();
    private boolean endReached = false;

    public FilePeekableCharacterStream(FileInputStream fis) {
        this.fis = fis;
    }

    @Override
    public boolean moreAvailable() {
        if (!buffer.isEmpty()) return true;
        if (endReached) return false;
        try {
            int next = fis.read();
            if (next == -1) {
                endReached = true;
                return false;
            }
            buffer.add(next);
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    // ... weitere Methoden
}

Schritt 2: Scanner – Tokenisierung nach Regeln

Der Scanner nimmt einen PeekableCharacterStream und eine Liste von Keywords entgegen. Er muss Tokens wie Identifier, IntConstant, FloatConstant, StringConstant, Operator und Invalid erkennen.

Token-Regeln im Überblick

  • Identifier: Beginnt mit Unterstrich oder Buchstabe, gefolgt von Buchstaben, Ziffern oder Unterstrich.
  • IntConstant: Optional negatives Vorzeichen, dann eine oder mehrere Ziffern.
  • FloatConstant: Wie IntConstant, aber mit optionalem Dezimalpunkt und Nachkommastellen.
  • StringConstant: In doppelten Anführungszeichen, mit Escape-Sequenzen wie \n oder \".
  • Operator: Einzelzeichen oder zweistellige Operatoren wie ==, !=, <=.
  • Invalid: Alles, was nicht in die obigen Kategorien fällt.

Besonderheiten

  • Whitespace wird übersprungen.
  • Ein negatives Vorzeichen vor einer Zahl wird als Operator behandelt, wenn das vorherige Token ein Identifier oder eine Konstante war.
  • Wenn ein Identifier oder eine Konstante direkt von einem Buchstaben oder Unterstrich gefolgt wird, gilt das Token als Invalid.

Ein Beispiel: Der Code int x = -5; wird tokenisiert als: Identifier "int", Identifier "x", Operator "=", Operator "-", IntConstant "5", Operator ";".

Schritt 3: CSVParser – CSV-Dateien parsen

Der CSVParser liest eine CSV-Datei mit einer Header-Zeile und gibt jede Datenzeile als Map<String, String> zurück. Die Header-Spalten müssen eindeutig und nicht leer sein.

CSV-Formatregeln

  • Jede Zeile wird durch einen Zeilenumbruch abgeschlossen.
  • Spalten werden durch Kommas getrennt.
  • Wenn eine Spalte Whitespace (Leerzeichen, Tabs, Zeilenumbrüche) enthält, muss sie in doppelten Anführungszeichen stehen.
  • Ein doppeltes Anführungszeichen innerhalb einer solchen Spalte wird durch zwei aufeinanderfolgende Anführungszeichen escaped.
  • Leere Spalten oder fehlende Spalten liefern null in der Map.

Der CSVParser kann auf dem PeekableCharacterStream aufbauen, den du bereits implementiert hast. Du musst die Zeichen lesen und die Felder entsprechend der Regeln extrahieren.

Häufige Fehler und Tipps

  • Vergiss nicht, den Stream zu schließen: In der close()-Methode solltest du auch den zugrunde liegenden FileInputStream schließen.
  • Beachte die Token-Reihenfolge: Beim Scanner musst du zuerst nach mehrstelligen Operatoren wie == suchen, bevor du einzelne Zeichen wie = als Operator erkennst.
  • Teste mit verschiedenen Dateien: Nutze die Beispiele aus dem Projektverzeichnis auf dem CSIF, um sicherzustellen, dass dein Parser korrekt funktioniert.

Abschluss und Ausblick

Mit diesen Implementierungen hast du die Grundlage für die weiteren Projekte gelegt. Der Scanner und CSVParser werden in späteren Aufgaben für die semantische Analyse und Codegenerierung verwendet. Denke daran, deine Lösung mit make clean zu bereinigen und als .tgz-Archiv abzugeben. Viel Erfolg!