CSV Datei einlesen



  • Guten Morgen,
    CSV Dateien sind ja wie TXT dateien, nur dass sie Datensätze zeilenweise abspeichern und diese mit ; voneinander trennen.

    Ich würde gerne das Datum (singular?) auslesen welches vor dem 8ten ; jeder Zeile kommt. Wie registriere ich, dass es sich um ein ; handelt?
    Speicher ich dann alles in char?
    Kann ich dann im Zeilendurchlauf nach auffinden des 8ten Zeichens wieder die Zeichen davor betrachten oder ist ein Zeilendurchlauf nur in die rechte Richtung möglich?

    Danke im Voraus


  • Mod

    Kann ich dann im Zeilendurchlauf nach auffinden des 8ten Zeichens wieder die Zeichen davor betrachten oder ist ein Zeilendurchlauf nur in die rechte Richtung möglich?

    Natürlich. Dafür nimmt man std::istream::seekg .
    Es ist aber recht umständlich. Am Besten liest du die Datei von Links nach Rechts aus.

    Wie registriere ich, dass es sich um ein ; handelt?

    Indem du das mit dem gelesenen Zeichen vergleichst 😕

    Eigentlich macht das aber std::basic_istream::ignore für dich, mit dem du alle Zeichen bis zum nächsten Delimitter überspringst (wobei der Delimitter in deinem Fall ';' wäre).

    Speicher ich dann alles in char?

    Wie wäre es mit std::tm ?



  • nehme dieses Helferlein:

    #include <istream>
    #include <limits> // numeric_limits
    
    struct skip_delimiter
    {
        skip_delimiter( char c, int anz )
            : zeichen_( c )
            , anz_( anz )
        {}
        char zeichen_;
        int anz_;
    };
    std::istream& operator>>( std::istream& in, skip_delimiter skippy )
    {
        for( ; skippy.anz_ > 0; --skippy.anz_ )
            in.ignore( std::numeric_limits< std::streamsize >::max(), skippy.zeichen_ );
        return in;
    }
    

    und wende ihn so an:

    ifstream file("datei.csv");
        int datum;
        if( file >> skip_delimiter(';',7) >> datum ) // vor dem 8'ten ist nach dem 7'ten ';'
            cout << datum << endl;
    

    oder siehe hier: http://www.c-plusplus.net/forum/p2292030#2292030

    Kromann schrieb:

    Speicher ich dann alles in char?

    besser nicht! Lese gleich das aus der Datei, was Du auch programm-intern benötigst.

    Kromann schrieb:

    Kann ich dann im Zeilendurchlauf nach auffinden des 8ten Zeichens wieder die Zeichen davor betrachten oder ist ein Zeilendurchlauf nur in die rechte Richtung möglich?

    möglich, aber nicht zu empfehlen. Besser Du liest es gleich vorher ein. Was genau willst Du lesen und wie ist das Format der CSV-Datei?

    Kromann schrieb:

    Danke im Voraus

    besser nachher Feedback geben 😉

    Nachtrag: das Helferlein skip_delimiter zählt auch Trennzeichen';', die ggf.. in Hochkomma eingeschlossen sind!



  • Arcoth schrieb:

    Kromann schrieb:

    Speicher ich dann alles in char?

    Wie wäre es mit std::tm ?

    Ich glaube hier hat Dich die Einzahl des Worts Daten auf den Holzweg geschickt... 🙂


  • Mod

    Datum schrieb:

    Arcoth schrieb:

    Kromann schrieb:

    Speicher ich dann alles in char?

    Wie wäre es mit std::tm ?

    Ich glaube hier hat Dich die Einzahl des Worts Daten auf den Holzweg geschickt... 🙂

    Jetzt verstehe ich das (singular?) im Text. (Dachte das bezog sich auf die Weise in der Eingelesen wird) Also ein vector von tm s?

    @Werner: Bitte korrigiere dein Helferlein. Das ist naemlich inkorrekt.

    Ich mache mal einen Vorschlag:

    struct skip_delimiter
    {
        skip_delimiter( char c, std::streamsize anz )
            : zeichen_( c )
            , anz_( anz )
        {}
        char zeichen_;
        std::streamsize anz_; // Hier lag der Fehler
    
        // Extra Helfer-Funktionen
        std::istream& ignore_one( std::istream& is ) const
        {
            return is.ignore( std::numeric_limits<std::streamsize>::max(), zeichen_ );
        }
    
        std::istream& ignore_all( std::istream& is ) const
        {
            std::streamsize s = anz_;
            while( s-- )
                ignore_one( is );
            return is;
        }
    };
    

    (ungetestet)



  • Dann besser gleich einen Parser verwenden, der korrekt auch mit dem Feldbegrenzerzeichen (und weiteren Features) umgehen kann, z.B.
    csv-parser-cplusplus
    fast-cpp-csv-parser


  • Mod

    Th69 schrieb:

    csv-parser-cplusplus

    Ieh!

    csv_parser file_parser;
    
            /* Define how many records we're gonna skip. This could be used to skip the column definitions. */
            file_parser.set_skip_lines(1);
    
            /* Specify the file to parse */
            file_parser.init(filename);
    

    Initialisierung über Funktionen und nicht Konstruktor? Und printf im Beispiel. Deutet auf nichts gutes hin.


Anmelden zum Antworten