EN · DE · RU · FR · ES

#1877: CSVWriter.java

projectforge-common/src/main/java/org/projectforge/common/CSVWriter.java Hilfsklasse — Paket org.projectforge.common, projectforge-common/src/main/java/org/projectforge/common/CSVWriter.java 176 Zeilen · 100 Code · 54 Kommentare · 22 leer
CSV-Ausgabe-Schreiber, der Daten in semikolongetrennte Textdateien formatiert. Begleitklasse zu CSVParser — bietet eine fließende Builder-API zum Schreiben von CSV-Zeilen mit korrektem Quoting. Unterstützt typisierte write()-Überladungen für Zeichenketten (mit doppelten Anführungszeichen-Escaping), lange Ganzzahlen, Datumsangaben (ISO-8601-Format) und generische Objekte. Konfigurierbares Trennzeichen, Zeilenende und Datumsformat. Wird für ProjectForge-Datenexporte verwendet (Adresslisten, Zeiterfassungsexporte, Finanzberichte).

Architektur

Importe

Konfiguration

EinstellungStandardSetter
CSV-Trennzeichen';' (Semikolon — europäische Konvention)setCsvSeparator(char)
Zeilenende"\n" (Unix-Zeilenumbruch)setCr(String)
Datumsformat"yyyy-MM-dd HH:mm:ss.SSS"setDateFormat(DateFormat)
Datums-ZeitzoneUTCIm Konstruktor fest codiert

Fließende Builder-API

Alle write()-Methoden geben this (die CSVWriter-Instanz) zurück, was Methodenverkettung ermöglicht:

csvWriter.write("Name").write("Alter").write(42L).writeEndOfLine();

Typspezifische Schreib-Überladungen

MethodeFormatierungAnführungszeichen
write(String s)Roher String mit " escaped zu "" (Verdopplung)Immer in "..." eingeschlossen — folgt den RFC-4180-Zitierregeln
write(long value)Direkte numerische Ausgabe über PrintWriter.print()Keine — Zahlen werden nicht in Anführungszeichen gesetzt
write(Date value)Formatiert über dateFormat.format() in UTCIn Anführungszeichen eingeschlossen — Datumsangaben können Leerzeichen oder Sonderzeichen enthalten
write(Object value)Fallback: String.valueOf(value)Keine — generische Objekte werden nicht zitiert (riskant bei Objekten mit Kommas/Anführungszeichen)

Zitieralgorithmus (Zeichenketten schreiben)

Die Methode write(String) implementiert korrektes CSV-Escaping gemäß RFC 4180:

  1. Ausgabe des Trennzeichens, wenn es nicht der erste Eintrag in der Zeile ist (verwaltet von writeSeparator() mit dem firstEntry-Flag)
  2. Ausgabe eines öffnenden doppelten Anführungszeichens (")
  3. Iteration durch jedes Zeichen der Zeichenkette
  4. Wenn das Zeichen ein doppeltes Anführungszeichen (") ist, wird es zweimal ausgegeben ("") — die Standard-CSV-Escape-Sequenz
  5. Alle anderen Zeichen werden unverändert ausgegeben
  6. Ausgabe eines schließenden doppelten Anführungszeichens (")

Zeilen schreiben

Trennzeichen-Logik (writeSeparator)

Das boolesche Flag firstEntry verfolgt, ob wir am Anfang einer Zeile stehen:

Dies ist ein klassisches Zustandsverfolgungsmuster für getrennte Ausgaben.

Integration mit CSVParser

CSVWriter definiert DEFAULT_CSV_SEPARATOR_CHAR = ';' als öffentliche Konstante, auf die CSVParser verweist, um ein konsistentes Standardtrennzeichen zwischen Leser und Schreiber sicherzustellen.

Vergleich mit modernen CSV-Bibliotheken

Diese Implementierung ist im Vergleich zu Apache Commons CSV oder OpenCSV bewusst minimalistisch:

Die Einfachheit spiegelt ihren Ursprung als zweckgebundenes Werkzeug für den ProjectForge-Datenexport wider, nicht als allgemeine CSV-Bibliothek.

Die Methode write(Object) setzt KEINE Anführungszeichen um die Ausgabe — sie ruft String.valueOf(value) auf und schreibt direkt. Wenn die toString()-Methode des Objekts eine Zeichenkette zurückgibt, die Kommas, Semikolons oder Zeilenumbrüche enthält, wird das resultierende CSV fehlerhaft sein. Dies ist akzeptabel, da von den Aufrufern erwartet wird, dass sie die typspezifischen Überladungen verwenden.
Die Datumsausgabe verwendet die UTC-Zeitzone — Daten werden vor der Formatierung auf UTC normalisiert. Dies ist eine bewusste Entscheidung für den Datenaustausch: Sie vermeidet Zeitzonen-Mehrdeutigkeiten in Exporten. Das Format "yyyy-MM-dd HH:mm:ss.SSS" ist ISO-8601-ähnlich, verwendet aber ein Leerzeichen anstelle von 'T'.

Git-Verlauf

868d6abb7 2025 -> 2026
63081666f Quelldatei-Header: 2024 -> 2025.
a73905c14 Tippfehler in projectforge*-Verzeichnissen korrigiert Gefunden mit codespell
b6092df09 Copyright 2023 -> 2024
ab45d51fa Copyright 2001-2022 -> 2001-2023.
5f7ef41b8 Copyright 2021 -> 2022
ceb63e8a1 Quellcode-Header: (C) 2001-2021.
7c79f1922 Copyright des Quell-Headers -> 2020.