Probleme beim Einlesen einer CSV Datei in ein 2dArray.



  • schlank0r schrieb:

    lin123 schrieb:

    Ich habe eine Große CSV. datei (Komma Separated VAlues)

    wieso speicherst du da extra kommas zwischen die werte, das ist doch gerade bei großen dateien ineffizient

    weil es ein weit verbreitetes format ist, das viele programme verstehen.
    was würdest du denn zwischen die werte packen, damit es 'effizienter' wird?
    🙂



  • ich würde einfach nichts dazwischen packen(braucht man ja auch nicht) und dann blockweise mit fread einlesen



  • also im binärmodus speichern würd ich das, dann entfällt auch die ineffiziente konvertierung von string nach double.



  • @schlank0r
    Die Kommas speichere ich doch nicht in meinem Array? ich verstehe nicht ganz was du meinst!
    Die csv datei ist mein Eingangsformat, da will ich nix dran ändern!

    @monstermunchkin
    Ja, das mit Float Array würd gehen aber die csv Datein sind bis zu 1Gb groß. Deswegen denke ich, wenn ich das array als int initialisiere, mein Programm deutlich weniger Arbeitsspeicher verwenden wird!

    Wenn ich statt str ein char array nehme, muss ich das mit einer bestimmten größe initialisieren?

    den char array "buffer" habe ich ja auch nicht mit einer bestimmten Länge angelegt, ist das nicht auch problematisch?



  • lin123 schrieb:

    Ja, das mit Float Array würd gehen aber die csv Datein sind bis zu 1Gb groß. Deswegen denke ich, wenn ich das array als int initialisiere, mein Programm deutlich weniger Arbeitsspeicher verwenden wird!

    float und int haben beide jeweils 4 Byte. Aber das kannst du machen wie du möchtest.

    lin123 schrieb:

    Wenn ich statt str ein char array nehme, muss ich das mit einer bestimmten größe initialisieren?
    den char array "buffer" habe ich ja auch nicht mit einer bestimmten Länge angelegt, ist das nicht auch problematisch?

    Kommt drauf an, was man vorhat. Das mit buffer ist schon richtig so.



  • Das Einlesen funktioniert soweit
    hier ist der Code:

    while (fgets (buffer, line_max, pFile) && zeile < Zeilen) { 
        spalte = 0; 
        if (zeile == 0) {
        	for (spalte=0; spalte<Spalten; spalte++){
        		csv_array[zeile][spalte] = 0; 
         	}
        	printf ("(test3)\n");
        } else {
            str = strtok (buffer, ","); 
            while (str != NULL && spalte++ < Spalten) { 
                csv_array[zeile][spalte] = atoi (str); 
                str = strtok (NULL, ","); 
            } 
        } 
        zeile++; 
    }
    

    Allerdings ergibt sich
    csv_array[zeile][0]=0
    csv_array[zeile][1]=Wert der ersten Spalte in der CSV
    der Erste Wert von Spalte ist doch 0 und nicht 1!



  • lin123 schrieb:

    Das Einlesen funktioniert soweit
    hier ist der Code:

    while (fgets (buffer, line_max, pFile) && zeile < Zeilen) { 
        spalte = 0; 
        if (zeile == 0) {
        	for (spalte=0; spalte<Spalten; spalte++){
        		csv_array[zeile][spalte] = 0; 
         	}
        	printf ("(test3)\n");
        } else {
            str = strtok (buffer, ","); 
            while (str != NULL && spalte++ < Spalten) { 
                csv_array[zeile][spalte] = atoi (str); 
                str = strtok (NULL, ","); 
            } 
        } 
        zeile++; 
    }
    

    Allerdings ergibt sich
    csv_array[zeile][0]=0
    csv_array[zeile][1]=Wert der ersten Spalte in der CSV
    der Erste Wert von Spalte ist doch 0 und nicht 1!

    Okay!! in der while schleife wird spalte bereits erhöht!



  • lin123 schrieb:

    Ich möchte von jedem Wert 2 Kommastellen einlesen deswegen mein :wert1=(float)*buffer; und wert1=wert1*100.

    Das wird so nicht gehen. Der schneidet Dir zuerst die Nachkommastellen ab und multipliziert dann mit 100. D. h. wenn buffer = 3.14 dann wert1 = 300 .
    EDIT 1: Gerade nochmal getestet: Der gibt Dir den ASCII-Wert von 3 zurück, also 51, und multipliziert dann mit 100.

    int wert1;
    wert1 = atof (buffer) * 100; // so ist's richtig
    


  • lin123 schrieb:

    Die csv datei ist mein Eingangsformat, da will ich nix dran ändern!

    doofes format bei so großen dateien



  • schlank0r schrieb:

    lin123 schrieb:

    Die csv datei ist mein Eingangsformat, da will ich nix dran ändern!

    doofes format bei so großen dateien

    garnicht. bei kleinen werten wirds sogar weniger.
    🙂



  • ;fricky schrieb:

    garnicht. bei kleinen werten wirds sogar weniger.
    🙂

    achwas.
    klein: 0.0000001
    😃



  • außerdem muss bei csv dateien zusätzlich noch konvertiert werden.
    vielleicht hat ja jemand mal lust nen test mit 1GB nutzdaten zu machen



  • schlank0r schrieb:

    außerdem muss bei csv dateien zusätzlich noch konvertiert werden.

    das muss immer sein, wenn ein allgemeines 'kanonisches' textformat verwendet wird. vorteil eines textformats ist ausserdem, dass es menschenlesbar ist, dass man's mit jedem editor bearbeiten kann, dass es keine steuerzeichen enthält, die programme verwirren könnten, usw. fast jede schäbige datenbank oder tabellenkalkulation kann CSV importieren. komprimieren lässt es sich auch sehr gut. binärformate sind eigentlich immer dann toll, wenn man nur sehr wenig rechenleistung, speicherplatz oder bandbreite hat. sonst sind textformate einfach viel praktischer (sogar XML und sowas).
    🙂



  • ja, ich lese auch ganz gern mal 1GB double werte quer.
    🙂



  • monstermunchkin schrieb:

    Das wird so nicht gehen. Der schneidet Dir zuerst die Nachkommastellen ab und multipliziert dann mit 100. D. h. wenn buffer = 3.14 dann wert1 = 300 .
    EDIT 1: Gerade nochmal getestet: Der gibt Dir den ASCII-Wert von 3 zurück, also 51, und multipliziert dann mit 100.

    int wert1;
    wert1 = atof (buffer) * 100; // so ist's richtig
    

    irgendwie klappt das nicht wirklich!
    buffer -- > wert1
    14.00 -- > 1400
    1195209 -- > 119520896



  • lin123 schrieb:

    monstermunchkin schrieb:

    Das wird so nicht gehen. Der schneidet Dir zuerst die Nachkommastellen ab und multipliziert dann mit 100. D. h. wenn buffer = 3.14 dann wert1 = 300 .
    EDIT 1: Gerade nochmal getestet: Der gibt Dir den ASCII-Wert von 3 zurück, also 51, und multipliziert dann mit 100.

    int wert1;
    wert1 = atof (buffer) * 100; // so ist's richtig
    

    irgendwie klappt das nicht wirklich!
    buffer -- > wert1
    14.00 -- > 1400
    1195209 -- > 119520896

    Bei mir geht's:

    int foo;
    char bar[] = "3.14";
    foo = atof (bar) * 100;
    printf ("%d", foo); // Ausgabe: 314
    


  • komisch...
    und bei Werten ohne Nachkommastellen?



  • lin123 schrieb:

    komisch...
    und bei Werten ohne Nachkommastellen?

    Funktionert auch. Poste doch bitte mal Deinen Teil des Codes, falls er von obigem abweicht.



  • monstermunchkin schrieb:

    Die Schleife ab Zeile 33 würde ich in etwa so machen:

    ...
    while (fgets (buffer, line_max, file) && zeile < Zeilen) {
        spalte = 0;
        // deine if-Abfage bzgl. der Zeile
        if (zeile == 0) {
            ...
        } else {
            str = strtok (buffer, ",");
            while (str != NULL && spalte++ < Spalten) {
                arr[zeile][spalte] = atoi (str);
                str = strtok (NULL, ",");
            }
        }
        zeile++;
    }
    ...
    

    Gez. monstermunchkin

    Morgen,
    Mein Code funktionniert mehr oder weniger, das Problem ist ich bekomme Speicherzugriffsfehler unter Linux. Unter Windows steigt er bei der Ersten While Schleife aus "Runtime check failure" es geht um die Variablen buffer und str die nicht initialisiert sind.
    Ich habe Sie folgendermassen deklariert:

    char *str;
    char *buffer;
    

    Das mit den Nackommastellen Poste ich sofort! Wie du siehst bin ich ein zeimlicher Anfänger!! Vielen dank für deine Hinweise! das ist echt cool und hilft mir hier weiter!



  • So Hier ist meine gesamte Schleife:

    ...
    	int c=0;
    	int n=0;
    
    	int str_int=0;
    	float str_float=0;
    
    while(c!='\n'){
        c = fgetc (pFile);
        n++;
    }
    	printf ("\n(test)Zeichen in Zeile 1:%i ",n);
    
    rewind(pFile);
    
    int line_max = n;
    
    int zeile = 0;
    int spalte = 0; 
    
    char *buffer;
    char *str;
    
    while (fgets (buffer, line_max , pFile) && zeile < Zeilen) {
    	printf ("\n\n CHECK zeile:%i",zeile);//test
    	spalte = 0;
    	if (zeile == 0) {
    //		for (spalte=0; spalte < Spalten; spalte++){
    		for (spalte=0; spalte < 3; spalte++){
    			printf("\n Loop1 zeile:%i  spalte %i wert: %i" ,zeile,spalte,str_int); //test
    			csv_array[zeile][spalte] = 1; 
    		}
    	} 
    	else {
    		str = strtok (buffer, ","); 
    //			while (str != NULL && spalte < Spalten) {
    			while (str != NULL && spalte < 3) {
    			str_float = atof (str) * 100;
    			str_float = str_float + 0.5; //Damit richtig gerundet wird
    			str_int = (int)str_float;
    			csv_array[zeile][spalte] = str_int; 
    			printf("\n Loop2 zeile:%i  spalte %i wert: %i" ,zeile,spalte,str_int); //test
    			str = strtok (NULL, ","); 
    			spalte++;
    		}
    	}
    	zeile++;
    	//Vorläufiger Abbruch
    	if (zeile==5){
    		printf("\n\n");
    		break;
    	}
    }
    

    1. Problem. Er steigt immer mit einem Speicherzugriffsfehler aus und zwar in der letzten Zeile (ohne den vorläufigen Abbruch). Ich habe zuvor getestet ob ich in die letzte Zeile was reinschreiben kann und es ging! Deswegen glaube ich nicht daß es an der initialisierung des Arrays liegt.

    2. Problem. Hier ist der output:

    CHECK zeile:0
    Loop1 zeile:0 spalte 0 wert: 0
    Loop1 zeile:0 spalte 1 wert: 0
    Loop1 zeile:0 spalte 2 wert: 0
    //bis hier alles korrekt
    CHECK zeile:1
    Loop2 zeile:1 spalte 0 wert: 0
    //weil zeile=1 geht er zu Else aber schreibt keinen Wert in mein Array und springt direkt weiter
    CHECK zeile:2
    Loop2 zeile:2 spalte 0 wert: 119520896 (Falsch, sollte 119520900 sein)
    Loop2 zeile:2 spalte 1 wert: 1600 (richtig)
    Loop2 zeile:2 spalte 2 wert: 1600 (richtig)
    //Die Werte in diesem Block sind Zwar richtig aber gehören nicht zu Zeile2 sondern zu Zeile 1
    CHECK zeile:3
    Loop2 zeile:3 spalte 0 wert: 119521000 (richtig)
    Loop2 zeile:3 spalte 1 wert: 1600 (richtig)
    Loop2 zeile:3 spalte 2 wert: 1600 (richtig)
    //Läuft bis zur vorletzten zeilen durch und bring ein Speicherzugrifffehler
    CHECK zeile:4
    Loop2 zeile:4 spalte 0 wert: 119521104 (Falsch, sollte 119521100 sein)
    Loop2 zeile:4 spalte 1 wert: 1600 (richtig)
    Loop2 zeile:4 spalte 2 wert: 1600 (richtig)


Anmelden zum Antworten