json.csv.de

Ratgeber · Format & Standards

CSV richtig escapen: der RFC-4180-Standard erklärt

CSV sieht trivial aus, bis ein Komma, ein Zeilenumbruch oder ein Anführungszeichen im Feld landet. RFC 4180 legt fest, wie korrekt escaped wird, damit Parser nicht stolpern.

7 Min Lesezeit 1.646 Wörter 4 FAQs
Jan-Tristan Rudat
Jan-Tristan RudatRedakteur
Geprüft am

CSV gilt als das einfachste tabellarische Format überhaupt: Werte durch Kommata trennen, Zeilen durch Zeilenumbrüche, fertig. Genau diese vermeintliche Einfachheit ist der Grund, warum CSV-Dateien in der Praxis so oft kaputt sind. Sobald ein Feld selbst ein Komma, einen Zeilenumbruch oder ein Anführungszeichen enthält, kollidiert der Inhalt mit den Strukturzeichen des Formats. Wer dann naiv konkateniert, produziert Dateien, die kein Parser deterministisch lesen kann.

RFC 4180 ist die Spezifikation, die diese Mehrdeutigkeiten auflöst. Sie ist kurz, präzise und beschreibt genau, wann ein Feld in doppelte Anführungszeichen muss und wie problematische Zeichen escaped werden. Dieser Artikel geht die Regeln durch, zeigt korrekte und falsche Beispiele direkt gegenüber und benennt die Fehler, die in echten Exporten am häufigsten auftauchen.

Die Grammatik von RFC 4180 in Kurzform

RFC 4180 definiert ein CSV als eine Folge von Datensätzen, getrennt durch CRLF. Jeder Datensatz besteht aus einem oder mehreren Feldern, getrennt durch ein Komma. Ein Feld ist entweder unquoted oder quoted, also in doppelte Anführungszeichen eingeschlossen. Die zulässigen Zeichen außerhalb von Quotes sind alles außer Komma, doppeltes Anführungszeichen, CR und LF. Genau diese vier Zeichen sind die Sonderzeichen des Formats.

Ein minimales, regelkonformes Beispiel sieht so aus:

name,stadt,plz
Anna Berg,Hamburg,20095
Tobias Reich,Köln,50667

Hier enthält kein einziges Feld ein Sonderzeichen, deshalb ist kein Quoting nötig. Die erste Zeile ist die optionale Header-Zeile. RFC 4180 erlaubt einen Header, schreibt ihn aber nicht zwingend vor. Der MIME-Type-Parameter header (present oder absent) signalisiert, ob eine Header-Zeile vorhanden ist. In der Praxis ist ein Header die Regel, weil er die Spaltenzuordnung beim Import absichert.

Wann ein Feld in Anführungszeichen muss

Der Kern der Spezifikation sind drei Bedingungen. Ein Feld muss genau dann in doppelte Anführungszeichen eingeschlossen werden, wenn es mindestens eines dieser Zeichen enthält:

SonderzeichenWarum problematischBehandlung
Komma ,Wird sonst als Feldtrenner interpretiertFeld in "..." einschließen
Doppeltes Anführungszeichen "Beendet ein Quoted Field vorzeitigVerdoppeln zu "" plus Feld quoten
CR (\r)Wird als Teil des Zeilentrenners gelesenFeld in "..." einschließen
LF (\n)Beendet sonst den DatensatzFeld in "..." einschließen
Führende/abschließende LeerzeichenWerden je nach Parser getrimmtOptional quoten, um sie zu erhalten

Sobald das Feld in Anführungszeichen steht, dürfen Komma, CR und LF darin frei vorkommen. Sie sind dann Teil des Wertes und nicht mehr Struktur. Nur das doppelte Anführungszeichen selbst bleibt auch innerhalb eines Quoted Field ein Sonderzeichen und braucht eine eigene Behandlung.

Komma im Wert

Das häufigste Problem. Ein Adressfeld oder ein Betrag mit Tausenderpunkt in englischer Notation kann ein Komma enthalten. Naiv geschrieben:

id,beschreibung,preis
1,Kabel, 2 Meter,9.99

Dieser Datensatz hat scheinbar drei Spalten, der Parser zählt aber vier Felder: 1, Kabel, 2 Meter und 9.99. Die Beschreibung ist auseinandergerissen, alle folgenden Spalten verschoben. Korrekt mit Quoting:

id,beschreibung,preis
1,"Kabel, 2 Meter",9.99

Jetzt ist Kabel, 2 Meter ein einziges Feld, das Komma darin ist geschützt. Drei Spalten, drei Werte.

Zeilenumbruch im Wert

Mehrzeilige Inhalte, etwa eine Postanschrift oder ein Kommentar mit Absätzen, enthalten LF oder CRLF. Ohne Quoting beendet der erste Umbruch den Datensatz mittendrin:

id,adresse,land
7,Hauptstraße 5
12045 Berlin,DE

Der Parser liest hier zwei Datensätze, der erste mit zwei Feldern, der zweite mit ebenfalls zwei Feldern, beide strukturell falsch. Korrekt eingeschlossen:

id,adresse,land
7,"Hauptstraße 5
12045 Berlin",DE

Der Zeilenumbruch steht innerhalb der Anführungszeichen und gehört damit zum Wert des Adressfeldes. Der Datensatz bleibt ein Datensatz mit drei Feldern, auch wenn er sich über zwei physische Zeilen erstreckt. Genau deshalb darf man CSV nicht zeilenweise mit einem simplen Split auf \n parsen, sondern muss den Quote-Zustand mitführen.

Anführungszeichen im Wert

Das ist der subtilste Fall. Ein doppeltes Anführungszeichen innerhalb eines Feldes wird durch Verdoppelung escaped, und das gesamte Feld wird zusätzlich in Anführungszeichen gesetzt. Beispiel: Der Wert 5" Display enthält ein Anführungszeichen (als Zoll-Zeichen). Falsch wäre:

id,produkt
3,5" Display

Der Parser sieht ein unquoted Field, das mitten im Wert ein " enthält, was nach RFC 4180 außerhalb von Quotes gar nicht zulässig ist. Das Ergebnis ist undefiniert, je nach Parser ein Fehler oder ein verstümmelter Wert. Korrekt:

id,produkt
3,"5"" Display"

Die äußeren Anführungszeichen markieren das Quoted Field, das verdoppelte "" in der Mitte steht für ein einzelnes " im Wert. Beim Lesen dekodiert der Parser "" zurück zu ", das Feld ergibt wieder 5" Display. Wer ein Feld behandelt, das sowohl Komma als auch Anführungszeichen enthält, kombiniert beide Regeln:

id,zitat
8,"Er sagte: ""hallo, welt"" und ging."

Der Wert lautet nach dem Parsen Er sagte: "hallo, welt" und ging. Das Komma ist durch das Quoting geschützt, die inneren Anführungszeichen durch Verdoppelung.

CRLF als Zeilentrenner

RFC 4180 schreibt CRLF (\r\n) als Trenner zwischen Datensätzen vor, optional auch nach dem letzten Datensatz. Reines LF, wie es unter Unix üblich ist, entspricht streng genommen nicht der Spezifikation. In der Praxis akzeptieren fast alle Parser auch LF, und viele Tools schreiben es. Trotzdem gibt es Konstellationen, in denen CRLF den Unterschied macht, etwa beim Import in ältere Excel-Versionen oder bei strikten Parsern, die exakt nach RFC arbeiten.

Wichtig ist die Konsistenz. Eine Datei sollte nicht mischen. Gemischte Zeilenenden entstehen oft, wenn ein Export auf einem System läuft und die Datei später auf einem anderen System Zeile für Zeile ergänzt wird. Ein Feld mit einem internen Umbruch sollte denselben Stil verwenden wie die Datensatztrenner, sonst entstehen schwer zu findende Inkonsistenzen. Beim Schreiben in Python steuert man das über das newline-Argument:

import csv

with open("export.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)  # schreibt standardmäßig CRLF
    writer.writerow(["id", "beschreibung", "preis"])
    writer.writerow([1, "Kabel, 2 Meter", "9.99"])

Das newline="" ist entscheidend. Ohne diese Angabe übersetzt der Text-Modus unter Windows das vom csv-Modul geschriebene \r\n ein zweites Mal, das Resultat sind doppelte Leerzeilen zwischen den Datensätzen. Das csv-Modul kümmert sich selbst um das korrekte Quoting nach RFC 4180, man muss es nicht von Hand bauen.

Die Header-Zeile

Der Header ist eine ganz normale Datenzeile, er folgt denselben Quoting-Regeln. Spaltennamen mit Komma oder Leerzeichen werden also genauso behandelt:

"laufende nr","betrag, brutto",notiz
1,119.00,"erste Rechnung"

Ein Header darf nicht garantieren, dass jede Datenzeile dieselbe Feldzahl hat, aber RFC 4180 verlangt, dass alle Datensätze dieselbe Anzahl Felder besitzen wie der Header. Parser, die sich strikt daran halten, melden Zeilen mit abweichender Feldzahl als Fehler. Genau hier zeigen sich unescapte Kommata zuerst: Eine Zeile hat plötzlich ein Feld zu viel.

Die häufigsten Fehler in echten Exporten

Unescapte Kommata. Der Klassiker. Felder werden ohne Rücksicht auf ihren Inhalt mit Komma verbunden. Sobald ein Wert selbst ein Komma trägt, verschiebt sich die gesamte Spaltenstruktur dieser Zeile. Symptom: einzelne Zeilen mit zu vielen Spalten, oft bei Adressen, Namen mit Titel oder Freitextfeldern.

Falsches Quoting von Anführungszeichen. Statt der Verdoppelung "" wird mit Backslash escaped (\"), wie man es aus JSON oder C-Strings kennt. RFC 4180 kennt keinen Backslash-Escape. Ein Parser, der nach Standard arbeitet, interpretiert \" als Backslash gefolgt vom Ende des Quoted Field und läuft danach aus dem Tritt. Falsch:

id,zitat
4,"Er sagte \"hallo\""

Korrekt nach RFC 4180:

id,zitat
4,"Er sagte ""hallo"""

Gemischte Trennzeichen. Eine Datei wird teils mit Komma, teils mit Semikolon geschrieben, etwa weil zwei Exportpfade unterschiedlich konfiguriert sind. Das Ergebnis liest sich für einen Parser als eine Datei mit völlig unterschiedlicher Spaltenzahl pro Zeile. Verwandt ist das deutsche Excel-Problem: Excel in deutscher Locale nutzt das Semikolon als Trenner, weil das Komma als Dezimaltrennzeichen belegt ist. Eine RFC-konforme Komma-CSV landet dann komplett in der ersten Spalte. Abhilfe: entweder bewusst mit Semikolon exportieren (was streng genommen nicht RFC 4180 ist, aber als CSV-Dialekt weit verbreitet), eine sep=;-Zeile als erste Zeile voranstellen, oder den Import-Assistenten statt des Doppelklicks nutzen.

Quoting nur teilweise. Manche Generatoren quoten ein Feld, escapen aber das innere Anführungszeichen nicht. Das Resultat ist ein vorzeitig geschlossenes Feld:

id,produkt
6,"5" Display"

Hier schließt das erste innere " das Quoted Field, der Rest (Display") ist undefiniert. Die Regel lautet immer: quoten und gleichzeitig verdoppeln, nie nur eines von beidem.

Vergessenes Quoting bei führenden Leerzeichen. Felder mit signifikanten führenden oder abschließenden Leerzeichen verlieren diese, wenn ein Parser trimmt. RFC 4180 selbst trimmt nicht, behandelt Leerzeichen also als Teil des Feldes, aber viele Implementierungen weichen davon ab. Wer Leerzeichen erhalten muss, quotet das Feld explizit.

Robust schreiben und robust lesen

Beim Schreiben ist die sicherste Strategie, eine erprobte Bibliothek zu verwenden statt selbst Strings zu konkatenieren. Das csv-Modul von Python, die entsprechenden Pakete in JavaScript, Java oder Go kennen die Quoting-Regeln und wenden sie konsistent an. Wer maximale Robustheit über minimale Dateigröße stellt, wählt den Modus Quote-All, bei dem jedes Feld in Anführungszeichen steht. Das ist immer RFC-konform und beseitigt jede Mehrdeutigkeit beim Trennzeichen, kostet aber etwas Speicher.

Beim Lesen gilt: niemals zeilenweise splitten. Ein korrekter Parser arbeitet zeichenweise oder tokenbasiert und führt einen Zustand mit, ob er sich gerade innerhalb eines Quoted Field befindet. Nur so erkennt er Kommata und Zeilenumbrüche, die zum Wert gehören, und dekodiert verdoppelte Anführungszeichen korrekt zurück. Ein zusätzlicher Stolperstein ist das Encoding: RFC 4180 sagt nichts über die Zeichenkodierung, in der Praxis ist UTF-8 Standard, aber ältere Excel-Exporte liefern oft Windows-1252. Ein BOM am Dateianfang hilft Excel beim Erkennen von UTF-8, kann aber andere Parser irritieren, die das BOM als Teil des ersten Feldnamens lesen.

Worauf es ankommt

RFC 4180 reduziert das CSV-Chaos auf eine Handvoll klarer Regeln: quoten, wenn das Feld Komma, Anführungszeichen oder Zeilenumbruch enthält, Anführungszeichen durch Verdoppelung escapen, CRLF als Datensatztrenner und konsistente Feldzahl pro Zeile. Die meisten Bugs entstehen, weil eine dieser Regeln halb umgesetzt wird, etwa Quoting ohne Verdoppelung oder Backslash statt "". Wer eine geprüfte Bibliothek zum Schreiben und einen zustandsbasierten Parser zum Lesen verwendet, umgeht praktisch alle dieser Fallen. Und wer eine CSV von Hand inspizieren muss, prüft zuerst Trennzeichen, Zeilenende und die Konsistenz der Spaltenzahl, denn dort sitzen die Fehler fast immer.

FAQ

Häufige Fragen

Muss ich jedes Feld in Anführungszeichen setzen?

Nein. RFC 4180 verlangt Quoting nur, wenn ein Feld das Trennzeichen, ein doppeltes Anführungszeichen oder einen Zeilenumbruch enthält. Viele Tools quoten trotzdem jedes Feld (Quote-All), das ist erlaubt und oft robuster, kostet aber Dateigröße.

Wie escape ich ein Anführungszeichen innerhalb eines Feldes?

Durch Verdoppelung. Ein doppeltes Anführungszeichen im Wert wird zu zwei doppelten Anführungszeichen, und das gesamte Feld wird zusätzlich in Anführungszeichen gesetzt. Aus 5" Display wird "5"" Display".

Welches Zeilenende schreibt RFC 4180 vor?

CRLF (\r\n) als Zeilentrenner zwischen Datensätzen. In der Praxis akzeptieren die meisten Parser auch reines LF, aber für maximale Kompatibilität, besonders mit Excel auf Windows, sollte CRLF geschrieben werden.

Warum zerschießt mein CSV in Excel die Spalten?

Meist liegt es am Trennzeichen. Excel in deutscher Locale erwartet das Semikolon, RFC 4180 schreibt das Komma vor. Entweder mit Semikolon exportieren oder eine sep=,-Zeile voranstellen, beziehungsweise den Import-Assistenten nutzen.

Anzeige

Quellen

Worauf dieser Ratgeber sich stützt

Veröffentlicht · zuletzt geprüft
Verantwortlich: Jan-Tristan Rudat
Anzeige
Anzeige
Anzeige
Anzeige