Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Probleme mit CSV Datei

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Probleme mit CSV Datei

    Hallo Leute,

    ich steh mal wieder vor nem rießen Problem.
    Und zwar geht es um eine CSV-Datei. Die bekomme ich von einem großen Shop. Diese muß ich in verschiedene kleinere aufteilen. Das ist auch alles kein Problem. Aber jetzt kommts. Die Daten sind per ';' getrennt. Ist ja auch so üblich.

    In der Datei gibt es auch eine Spalte Beschreibung. Dort steht längerer Text drin. Jetzt haben die Schlaumeier von dem Shop in diesen Texten ';' gesetzt.
    Dadurch geht natürlich die Aufteilung mit explode dahin

    Da auf der Spalte Text eine Spalte folgt wo die Einträge immer mit einer Zahl beginnen, hab ich mir folgendes gedacht.

    Also ich zerlege die Zeile mit explode. Dann prüfe ich ob wert[19] als 1. Zeichen eine Zahl hat. Wenn nicht, wird wert[19] an wert[18] angehängt
    und es geht von vorne los.
    Hier mal mein Versuch der Umsetzung:

    PHP-Code:
    private function delSemi($datei)
    {
       
    $src file(dirname(__FILE__).'/../import/'.$datei);
       
    $dst fopen(dirname(__FILE__).'/../import/test.csv''w+');
       foreach(
    $src as $zeile)
          {
             
    $werte explode(';'$zeile); // CSV Datenzeile in Array umwandeln
             
    $zeichen=substr($werte[19],0,1); //erstes Zeichen von $werte[19] auslesen   
             
    if(!preg_match('/^[0-9]/'$zeichen))     
             {
                
    $werte[18].="+".$werte[19];
                
    $this->delSemi();
             } 
    //if pregmatch (wenn erstes Zeichen von werte[19] keine Zahl ist)
             
    else
             {
                
    $text=$werte[0].$werte[1].$werte[2].$werte[3].$werte[4].$werte[5].$werte[6].$werte[7].$werte[8].$werte[9].$werte[10].$werte[11].$werte[12].$werte[13].$werte[14].$werte[15].$werte[16].$werte[17].$werte[18].$werte[19].$werte[20].$werte[21].$werte[22].$werte[23];
                
    fwrite($dst$text);
             } 
            } 
    // foreach 
    Leider funktioniert das nicht wie es soll.
    Ich erhalte folgenden Fehler:

    Code:
    Fatal error:  Allowed memory size of 134217728 bytes exhausted  (tried to allocate 8308722 bytes) in AdminCSV.php  on line 292
    Hat jemand eine Idee wie das zu realisieren ginge?
    Ich wäre wirklich sehr dankbar.


  • #2
    Wenn im CSV in einem Datenfeld das Trennzeichen verwendet wird, müssen auch Feldbegrenzer verwendet werden. Ist einfach so, anderenfalls kann nicht automatisiert entschieden werden, wo das eine Feld aufhört und das andere beginnt.
    Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

    Kommentar


    • #3
      Ja und wie soll mir das jetzt helfen?

      Kommentar


      • #4
        Lass dir die Daten in einem Format liefern, das automatisiert weiterverarbeitet werden kann.

        Das angesprochene Format (Trennzeichen in Daten enthalten, keine Feldbgrenzer) ist ungültig. Exakt aus diesem Grund gibt es ja die Feldbegrenzer.

        Was anderes ist dazu IMHO nicht zu sagen. Ich schlage mich täglich mit so einem Mist herum und sehe es inzwischen nicht mehr ein, gegen die Dummheit und Ingnoranz anderer Leute Patches und Fixes entwickeln zu müssen, oder ständig schon fertigen Code ändern zu müssen, bloss weil das Datenformat wieder mal "angepasst" wurde.
        Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

        Kommentar


        • #5
          Für sowas gibt es übrigens die Funktionen fputcsv und fgetcsv.

          Der Code, den du zeigst, kann irgendwie gar nicht laufen.

          Hier fehlt ein Argument: $this->delSemi(); (Die Rekursion ist aber eine wahrscheinliche Ursache für den Speicherüberlauf.)

          Außerdem ist die Anzahl der geschweiften Klammern unbalanciert.

          Abgesehen davon hat lstegelitz natürlich Recht: Wenn es keine Möglichkeit gibt, sauber zu unterscheiden, ob es sich um ein Semikolon im Text oder ein Trennzeichen handelt, kannst du das automatisierte Weiterverarbeiten im Grunde vergessen.

          Wenn die Spalte Beschreibung die *einzige* Spalte ist, die "falsche" Semikolons enthält, kann man es sich zurechtrechnen. (Die Annahme halte ich aber für spekulativ, außerdem wäre es natürlich völlig unsauber.) In diesem Fall wären Testdaten gut. Macht es den Helfern doch nicht immer so schwer...

          Edit: @6: Siehe fgetcsv.

          Kommentar


          • #6
            Also als Feldbegrenzer scheint das " zu dienen.
            Also müßte man den Text zwischen den "-Zeichen nehmen,
            und in diesem alle ; zu sagen wir + machen.

            Ne Idee wie das funktionieren könnte?

            Kommentar


            • #7
              Brauchst nix ersetzen...

              Wenn Feldbegrenzer verwendet werden, kann ZWISCHEN zwei Feldbegrenzern auch ein Trennzeichen auftauchen...
              Code:
              "1234";"dies ist ein Text; auch mit Semikolon";"test"
              Einziges Problemchen: Taucht nun ein Feldbegrenzer in den Daten auf, muss dieser escaped sein. Ein halbwegs gescheiter Exporter sollte mit sowas aber umgehen können.
              Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

              Kommentar


              • #8
                Genau da liegt ja mein Problem.

                Ich teile die Zeile mit explode() und dem Trennzeichen ; auf.
                Ist jetzt ein Semikolon im Text vorhanden
                Code:
                1;"das ist einText; mit einem Trennzeichen drin";23;0;bla
                zerschießt es mir ja mein Array. Weil Array[2] ist dann nicht 23
                sondern ' mit einem trennzeichen drin'

                Also müßte ich das Semikolon zuerst ersetzen und dann teilen.
                Nur leider weiß ich nicht wie?
                Oder gibt es die Möglichkeit mit Hilfe von Windows Scripting Host
                eine Textdatei in csv umzuwandeln mit selbstdefinierten Trennzeichen?

                Kommentar


                • #9
                  Spricht irgendwas gegen [MAN]fgetcsv[/MAN]?

                  PS:
                  $text=$werte[0].$werte[1].$werte[2].$werte[3].$werte[4].$werte[5].$werte[6].$werte[7].$werte[8].$werte[9].$werte[10].$werte[11].$werte[12].$werte[13].$werte[14].$werte[15].$werte[16].$werte[17].$werte[18].$werte[19].$werte[20].$werte[21].$werte[22].$werte[23];
                  Gruselcode²
                  --

                  „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                  Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                  --

                  Kommentar


                  • #10
                    Hab ich denn mit fgetcsv() nicht das selbe Problem?
                    Oder werden da die Daten korrekt getrennt?

                    Gruselcode²
                    Das stimmt wohl. War ja auch nur ne Idee. Und auch nicht das Hauptproblem.
                    Wird dann schon noch angepasst

                    Kommentar


                    • #11
                      Hab ich denn mit fgetcsv() nicht das selbe Problem?
                      Ausprobieren?

                      [edit]
                      Ok, hab jetzt noch mal alles richtig gelesen. Stimmt - da kann man nichts weiter sagen als lstegelitz in #4/
                      --

                      „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                      Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                      --

                      Kommentar


                      • #12
                        PHP-Code:
                        <?php

                        $row 
                        1;
                        if ((
                        $handle fopen("test.csv""r")) !== FALSE) {
                            while ((
                        $data fgetcsv($handle0";"'"')) !== FALSE) {
                                
                        $num count($data);
                                echo 
                        "<p> $num fields in line $row: <br /></p>\n";
                                
                        $row++;
                                for (
                        $c=0$c $num$c++) {
                                    echo 
                        $data[$c] . "<br />\n";
                                }
                            }
                            
                        fclose($handle);
                        }
                        test.csv:

                        Code:
                        1;"das ist einText; mit einem Trennzeichen drin";23;0;bla
                        Ausgabe:

                        Code:
                        5 fields in line 1:
                        
                        1
                        das ist einText; mit einem Trennzeichen drin
                        23
                        0
                        bla
                        Edit: @#13: Ich glaube, da ist man sich nicht so sicher, ob das Format gültig ist. Ich vermute aber, es ist es.

                        Kommentar


                        • #13
                          Ja, aber er hat ja wohl kein gültiges CSV-Format..

                          [edit] Oder doch? (# Man, ich kann heute nicht richtig lesen.
                          --

                          „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                          Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                          --

                          Kommentar


                          • #14
                            Ich habs mal mit fgetcsv() versucht und siehe es geht

                            PHP-Code:
                            while(($werte=fgetcsv($src8192";"))!==FALSE
                            Was ich mich jetzt nur frage, wieso? Was macht fgetcsv()
                            anders als mit explode?
                            Ich hab ja nicht mal ein $enclosure angegeben.
                            Welchen Wert nimmt man eigentlich für int $length?

                            Kommentar


                            • #15
                              Ich hab ja nicht mal ein $enclosure angegeben.
                              " ist Standard für CSV. Ich denke, dem ist der Automatismus geschuldet.
                              Was macht fgetcsv() anders als mit explode?
                              Es liest halt CSV aus/interpretiert Text als CSV-Zeile. Separator, Enclosures (, New lines) - mehr Regeln hat ja CSV nun nicht.
                              --

                              „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                              Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


                              --

                              Kommentar

                              Lädt...
                              X