Micha: Einlesen einer CSV-Datei

Hallo zusammen,

ich möchte eine CSV-Datei lesen. Solange diese "einfach" aufgebaut ist, reicht vermutlich ein einfaches split(","). Im Netz werden auch unzählige Reguläre Ausdrücke angeboten wie bspw. (?:\s*(?:"([^"])"|([^,]+))\s,?|(?<=,)(),?)+?, die auch Quotes usw. berücksichtigen. Auch diesen könnte ich mit split() sicher direkt nutzen, sodass mein Quellcode nur unwesentlich anders aussehen würde.
Wenn ich mir hingegen den Quellcode vom opencsv-Projekt ansehe, wird dort Zeichen für Zeichen gelesen und ausgewertet. Sind Reguläre Ausdrücke zum Zerlegen von CSV-Dateien ungeeignet, ist deren Performance (deutlich) schlechter, oder warum verzichten Bibliotheken auf diese Technik?

Schöne Grüße
Micha

  1. Meine Herren,

    Welche Programmiersprache benutzt du? Im Falle von PHP wirf mal einen Blick auf fgetcsv und str_getcsv.

    --
    Hey Girl,
    i wish you were asynchronous, so you'd give me a callback.
    1. Hallo 1UnitedPower,

      Welche Programmiersprache benutzt du?

      Es war eine generelle Frage. Konkret wäre es schon Java sollte aber für das Antwort nicht auf diese runtergebrochen werden, weil es mir mehr um die Technik ging.

      Schöne Grüße
      Micha

      1. Der CSV-Standard ist für manche Zwecke nicht ausreichend.

        Man trennt Feldinhalte mit einem Zeichen, oft dem Semikolon. Dann kann man die Feldinhalte zusätzlich in Quotes setzen.

        Aber wann ist eine Gruppe von Values fertig?

        Am Zeilenumbruch nicht unbedingt, denn ein per CSV übermitteltes Beschreibungsfeld kann selbst Zeilenumbrüche enthalten und dummerweise sogar eine Zeile mit einem Quote beenden.

        Die Values, die noch zu dieser Gruppe gehören, werden dann als neue Gruppe angesehen, die natürlich zu wenig Felder hat.

        Kennt jemand eine Lösung für dieses Problem?

        Gast

        1. Hallo

          [...]dummerweise sogar eine Zeile mit einem Quote beenden.

          Kennt jemand eine Lösung für dieses Problem?

          ich bin nicht sicher ob ich dir folgen konnte, aber das klingt nach einem Fehler beim Erstellen der csv-Datei.
          Üblicherweise sollte in einem Feld kein unmaskierter Quote vorkommen. Eigentlich gibt es genügend unterschiedliche Quotes, sodass die von dir beschriebene Kollision vermeidbar ist.

          Gruß
          Kalk

          1. Hallo Kalk,

            ich habe das Einlesen einer CSV-Datei mit fgetcsv versucht. Soll angeblich ein Array mit den Values ergeben.

            ich bin nicht sicher ob ich dir folgen konnte, aber das klingt nach einem Fehler beim Erstellen der csv-Datei.

            Habe noch mal erstellt. | (pipe) ist Feldtrenner, " ist quote. Lese ein mit
            while ( $arr_felder = fgetcsv( $handle, 0, "|" ))

            ...|"Zum 21. Mal verwandelt sich die Heppenheimer Altstadt in eine große Open-Air-Bühne, wenn das internationale Straßentheaterfestival "Gassensensationen" Vorstellungen auf hohem Niveau bietet. Von Artistik und Comedy bis hin zu stillen und poetischen Momenten reicht die Spannbreite der Inszenierungen. Albert Völkl, der als "Laternenmacher" bekannt ist, zeigt sein neues Figurentheater, zu sehen sind auch die Pantomimen Bodecker & Neander aus Berlin und viele andere mehr.
            Der Eintritt zu allen Veranstaltungen ist frei, um allen Bevölkerungsgruppen den Zugang zum Festival zu ermöglichen."|"Beginn ab jeweils 19:00...

            "Der Eintritt ... " wird als neuer Satz interpretiert. Es gibt andere Sätze, die sehr wohl einen Zeilenumbruch im Textfeld haben und korrekt behandelt werden.

            Kannst du was erkennen?

            Gast

            1. ich sehe, dass das Problem nur dann auftritt, wenn " quotes im Text vorkommen, allerdings nicht direkt nach "

              Habe jetzt das Zeichen ` als Feldbegrenzer gewählt und es funktioniert. Eine Maskierung der Quotes ist in dem Programm das CSV erstellt, nicht vorgesehen.

              Mein PHP Kommando heisst jetzt
              while ( $arr_felder = fgetcsv( $handle, 0, "|", "" ))`

              Gast

              1. Tach!

                ich sehe, dass das Problem nur dann auftritt, wenn " quotes im Text vorkommen, allerdings nicht direkt nach "

                Ein " nach einem " sieht für einen korrekt arbeitenden CSV-Leser wie ein einzelnes " aus. Damit wäre zwar das " durch das Feldbegrenzer-" maskiert, aber insgesamt ist das Feld nicht eingerahmt. Das müsste bei einem darin enthaltenen Zeilenumbruch negative Auswirkungen haben.

                Habe jetzt das Zeichen ` als Feldbegrenzer gewählt und es funktioniert. Eine Maskierung der Quotes ist in dem Programm das CSV erstellt, nicht vorgesehen.

                Dann erstellt das Programm nur ein an CSV angelehntes aber unbrauchbares Dateiformat. Gut, dass CSV so flexibel ist, dass du mit alternativen Begrenzungszeichen doch noch ans Ziel kommst. - Bis zu dem Tag, an dem sich einer der Content-Lieferanten denkt, dass man zur Abwechslung ja mal mit `` eingerahmte Texte schreiben kann. Möge er in weiter Ferne liegen (ob Tag oder Lieferant bleibt sich dabei gleich).

                dedlfix.

        2. Tach!

          Der CSV-Standard ist für manche Zwecke nicht ausreichend.

          Das halte ich für ein Gerücht.

          Man trennt Feldinhalte mit einem Zeichen, oft dem Semikolon. Dann kann man die Feldinhalte zusätzlich in Quotes setzen.
          Aber wann ist eine Gruppe von Values fertig?

          Am Zeilenumbruch, der sich nicht in einem gequoteten Wert befindet.

          Am Zeilenumbruch nicht unbedingt, denn ein per CSV übermitteltes Beschreibungsfeld kann selbst Zeilenumbrüche enthalten und dummerweise sogar eine Zeile mit einem Quote beenden.
          Die Values, die noch zu dieser Gruppe gehören, werden dann als neue Gruppe angesehen, die natürlich zu wenig Felder hat.

          Nö. Man quotet Werte, die Trennzeichen enthalten (können). Zu diesen Trennzeichen zählt nicht nur der Feldtrenner sondern auch der Datensatztrenner.

          Kennt jemand eine Lösung für dieses Problem?

          Der CSV-Standard.

          feld1;feld2;feld3
          foo;"bar ""qux"" baz
          corge";grault
          gapply;"waldo;fred";plugh

          dedlfix.

  2. Wenn ich mir hingegen den Quellcode vom opencsv-Projekt ansehe, wird dort Zeichen für Zeichen gelesen und ausgewertet. Sind Reguläre Ausdrücke zum Zerlegen von CSV-Dateien ungeeignet

    Ja.

    Wenn du dich schon mal mit Grammatiken (hier in BNF abgebildet) beschäftigt hast, siehst du leicht, dass diesem Problem mit Regex¹ nicht beizukommen ist. Verwende immer einen Parser.

    ¹ So wie die Beispiele, also das Äquivalent von DFA. Regex, die Code enthalten dürfen, schaffen das natürlich.