texfile in einen vector



  • Du machst das denke ich viel zu kompliziert.. Zeig nochmal genau, was du für ein File hast und wie das genau haben willst.

    Hier einfach mal boost zu benutzen macht das ganze nicht besser.



  • Also habe ein simples textfile:

    feld1(varchar);feld2(varchar);feld3(varchar);......feldn(varchar)

    und das ganze mal 5mio zeilen oder 3mio also immer ziemlich gross..
    und ich experimentiere gerade wie ich das ganze sehr schnell und speichersparend in ein 2d raster(zeile/spalte) bekomme.. das ist alles

    P.S.: besten dank fürs einklinken....



  • Und wie genau willst du das in mehrere Dimensionen unterteilen?
    Und welche Daten von dem File willst du auch speichern?

    Mach mal ein kleines Beispiel mit 2-3 Einträgen, wie ein Inputfile aussieht und wie du das dann gespeichert haben willst.



  • Also:

    feld1;feld2;feld3
    hans;mercedes;new york
    evelyn;trabant;moskau

    Und jetzt will ich das ganze in ein quasi zwei dimensionales array packen

    ich will jede zeile und spalte mit einem index ansprechen können...

    klar genug



  • ismaild schrieb:

    feld1(varchar);feld2(varchar);feld3(varchar);......feldn(varchar)

    Keinerlei Infos über Redundanz, Inhalt, Größe?

    ismaild schrieb:

    sehr schnell und speichersparend

    Speichersparend bei beliebigem Text wird bei 1char pro Zeichen sein ... wenn du keine wilden Sonderzeichen drin hast. Du könntest versuchen längere Textpassagen mit Pack-Algos zu verkleinern (bz2?) was aber Rechenzeit zu en/dekodieren verbraucht also dem "sehr schnell" entgegenspricht.

    Wirklich platzsparend wird das nur gehen wenn in den 5 mio Zeilen * n spalten
    der selbe Text immer wieder kommt ... dann könntest du eine Qmap < QString, int> nehmen (jedem Text eine ID zuweisen) und dann die Ints speichern ... wäre kürzer sofern der meiste Text >> 4 characters hat ...

    Bei der Dateigröße ist mE allerdings ein sequentielles Auslesen besser ...

    5 mio Zeilen, 4 chars pro spalte, 10 values pro Zeile
    = 5.000.000 * 4 * 10
    = 200.000.000 chars (ohne seperatoren) / 1024 / 1024
    = 190 MB Daten



  • So hab mal bischen modifiziert.

    int main(int argc, char* argv[])
    {
        const char *delims = ";";
        const char* fname = "3mio.txt";
        FILE *fp = fopen( fname, "rb" );
    
        fseek(fp, 0, SEEK_END);
        long pos = ftell(fp);
        fseek(fp, 0, SEEK_SET);
    
        char *bytes = (char *)malloc(pos);
        fread(bytes, pos, 1, fp);
    
        fseek(fp, 0, SEEK_SET);
        int lines(0),cols(0);
        int i(0);
        for (; i<=pos; i++)
        {
            if(bytes[i] == *delims && lines < 1)
                cols++;
            if(bytes[i] == '\n')
                lines++;
        }
        free(bytes);
        cols++;
    
        typedef boost::multi_array<char*, 2> array_type;
        typedef array_type::index index;
        array_type meineDaten(boost::extents[lines][cols]);
        std::ofstream datei("cout.txt");
    
        char buff[BUFSIZ]; 
        int x = setvbuf(fp, (char *)NULL, _IOLBF, BUFSIZ*10);
        int imyline(0),imycol(0);
        size_t start = 0;char token[50];
    
        while ( fgets( buff, sizeof buff, fp ) != NULL )
        {
            while (buff[start] != '\0')
            {
                size_t end = strcspn(buff + start, delims);
                strncpy(token, buff + start, end);token[end]= '\0';
                meineDaten[imyline][imycol]=_strdup(token);
                start += (buff[start + end] != '\0') ? end + 1 : end;
                imycol++;
            }
            start = 0;
            imyline++;
            imycol=0;
        }
        //_getch();
        for(index i = 0; i != lines; ++i)
            datei << meineDaten[i][9] << "\n";
        return 0;
    }
    

    Und was meint Ihr...??

    Hat einer einen Vorschlag wie ich in der inneren while-schleife das stringcopy direkt in mein array bekomme sodass ich _strdup() mir sparen könnte..

    Für jede verbesserug bin ich offen.
    Achja habs diesmal mit dem boost gemacht...
    der Speicher bewegt sich bei ca. 800mb aber ist ziemlich schnell..

    P.S.: wusstet Ihr das es schneller ist ein <<"\n"; anzuhängen als <<endl; zu benutzen.....nur mal so in den Raum geschmissen



  • liegt denke ich daran, dass endl nicht nur \n ist sondern auch flush, also den Schreibbuffer in die Datei zwangsentleert statt dann, wenn das OS dazu hat.



  • Ih versuche gerade mal einen natives array zu benutzen, aber irgendwie ist es net so intuitiv wir der von boost.

    Also habe ein

    char* array_2D[lines][cols];
    

    wie muss ich jetzt dem array mein token übergeben....??



  • So habe es jetzt fertig...

    int main(int argc, char* argv[])
    {
        unsigned int startTime = 0;
        unsigned int endTime = 0;
    
        const char *delims = ";";
        const char* fname = "5mio.txt";
        FILE *fp = fopen( fname, "rb" );
    
        fseek(fp, 0, SEEK_END);
        long pos = ftell(fp);
        fseek(fp, 0, SEEK_SET);
    
        char *bytes = (char *)malloc(pos);
        fread(bytes, pos, 1, fp);
    
        fseek(fp, 0, SEEK_SET);
        int lines(0),cols(0);
        int i(0);
        for (; i<=pos; i++)
        {
            if(lines < 1 && bytes[i] == *delims)
                cols++;
            if(bytes[i] == '\n')
                lines++;
        }
        free(bytes);
        cols++;
    
        // Create the native array
        char*** myArray=allocate_2d_array_of_chars(lines,cols);
        std::ofstream datei("cout.txt");
    
        char buff[BUFSIZ];
        int x = setvbuf(fp, (char *)NULL, _IOLBF, BUFSIZ*10);
        int imyline(0),imycol(0);
        while ( fgets( buff, sizeof buff, fp ) != NULL )
        {
            while (buff[start] != '\0')
            {
                size_t end = strcspn(buff + start, delims);
                char token[end];
                char szString[end];
                szString[end]='\0';
                strncpy(token, buff + start, end);
                token[end]='\0';
                if(imycol== (cols-1))
                {
                    int i2 = 0;
                    for (int i = 0; i < end; i++)
                    {
                        char c = token[i];
                        if (c != '\r' && c != '\n')
                        {
                            szString[i2++] = c;
                            szString[i2]='\0';
                        }
                    }
                    myArray[imyline][imycol]=_strdup(szString);
    
                }
                else
                {
                    myArray[imyline][imycol]=_strdup(token);
    
                }
                start += (buff[start + end] != '\0') ? end + 1 : end;
                imycol++;
            }
            start = 0;
            imyline++;
            imycol=0;
        }
    
        for(int i = 0; i < lines; ++i)
        {
            for(int j = 0; j < cols; ++j)
            {
                (j==0)?(datei << myArray[i][j]):(datei << delims << myArray[i][j]);
            }
            datei << "\n";
        }
    
        return 0;
    }
    
    char*** allocate_2d_array_of_chars(size_t rows, size_t columns)
    {
        int i;
        char ***db_array;
    
        db_array = (char ***)malloc ( rows * sizeof *db_array);
    
        if ( db_array == NULL )
        {
            puts ("Speicherreservierung nicht möglich");
            return NULL;
        }
    
        for ( i = 0; i<rows; i++)
        {
            db_array[i] = (char **)malloc ( columns * sizeof *db_array[i]);
            if ( db_array[i] == NULL )
                printf ("Speicherreservierung bei db_array[%d] nicht möglich\n", i);
        }
    
        return db_array;
    }
    

    Hab da mal ne Frage...Wenn ich die Datei einlese habe ich am Ende einer jeden Zeile ein \r\n.. soweit ja kein Problem, aber wenn ich selber versuche diese beim schreiben in die Datei wieder einzusetzen bekomme ich noch eine Leerzeile zwischen den Zeilen....

    Und noch was.. die Datei die ich einlese hat ca. 300mb, wenn die Datei im Array ist habe ich einen Seicherverbrauch bei ca. 900mb, also man müsste meinen die Datei wird redundant gepeichert oder so...



  • Habe nochmal versucht mit memory mapped files die Sache etwas zu beschleunigen.

    hier der Code:

    namespace io = boost::iostreams;
    int main(int argc, char* argv[])
    {
        unsigned int startTime = 0;
        unsigned int endTime = 0;
    
        const char *delims = ";";
        const char* fname = "5mio.txt";
        FILE *fp = fopen( fname, "rb" );
    
        fseek(fp, 0, SEEK_END);
        long pos = ftell(fp);
        fseek(fp, 0, SEEK_SET);
    
        char *bytes = (char *)malloc(pos);
        fread(bytes, pos, 1, fp);
    
        fseek(fp, 0, SEEK_SET);
        int lines(0),cols(0);
        int i(0);
        for (; i<=pos; i++)
        {
            if(lines < 1 && bytes[i] == *delims)
                cols++;
            if(bytes[i] == '\n')
                lines++;
        }
        free(bytes);
        cols++;
    
        io::mapped_file_source myMap("5mio.txt");
        io::stream<io::mapped_file_source> input(myMap);
        // Create the native array
        char*** myArray=allocate_2d_array_of_chars(lines,cols);
        std::ofstream datei("cout.txt");
        std::string line;
    
        char buff[BUFSIZ];
    
        int imyline(0),imycol(0);
    
        while(std::getline(input, line))
        {
            strcpy(buff,line.c_str());
            while (buff[start] != '\0')
            {
                size_t end = strcspn(buff + start, delims);
                char token[end];
                char szString[end];
                szString[end]='\0';
                strncpy(token, buff + start, end);
                token[end]='\0';
                if(imycol== (cols-1))
                {
                    int i2 = 0;
                    for (int i = 0; i < end; i++)
                    {
                        char c = token[i];
                        if (c != '\r' && c != '\n')
                        {
                            szString[i2++] = c;
                            szString[i2]='\0';
                        }
                    }
                    myArray[imyline][imycol]=_strdup(szString);
                }
                else
                {
                    myArray[imyline][imycol]=_strdup(token);
                }
                start += (buff[start + end] != '\0') ? end + 1 : end;
                imycol++;
            }
            start = 0;
            imyline++;
            imycol=0;
        }
    
        for(int i = 0; i < lines; ++i)
        {
            for(int j = 0; j < cols; ++j)
            {
                (j==0)?(datei << myArray[i][j]):(datei << delims << myArray[i][j]);
            }
            datei << "\n";
        }
    
        return 0;
    }
    
    char*** allocate_2d_array_of_chars(size_t rows, size_t columns)
    {
        int i;
        char ***db_array;
    
        db_array = (char ***)malloc ( rows * sizeof *db_array);
    
        if ( db_array == NULL )
        {
            puts ("Speicherreservierung nicht möglich");
            return NULL;
        }
    
        for ( i = 0; i<rows; i++)
        {
            db_array[i] = (char **)malloc ( columns * sizeof *db_array[i]);
            if ( db_array[i] == NULL )
                printf ("Speicherreservierung bei db_array[%d] nicht möglich\n", i);
        }
    
        return db_array;
    }
    

    Die Sache ist das Dingen mit Mapping ist langsamer, ca. 3sek.
    komisch oder....

    P.S.: Bin für jede Verbesserung offen und dankbar...


Anmelden zum Antworten