Einlesen einer Datei: Geschwindigkeitsoptimierung



  • Original erstellt von Konstantin:
    **Nimmt so etwas wirklich soooo viel Zeit in Anspruch??? Das hätt ich ja nicht gedacht! Das gibt mir ja echt zu denken...
    **

    beispiel hier:
    rtrn = rtrn + buf + "\r\n";

    in rtrn stehen sagen wir 100KB
    dann werden

    rtrn = rtrn + buf + "\r\n";
                ^
    

    diese 100KB hier einmal kopiert und den inhalt von buf kommt auch noch rein.

    rtrn = rtrn + buf + "\r\n";
                      ^
    

    hier wird das ganze dann nochmal gemacht - 100KB kopiert und "\r\n" drangehaengt...

    das ganze wird dann rtrn zugewiesen, also wird nochmal alles kopiert.

    oder zB hier:
    rtrn = rtrn.substr(0, rtrn.length() - 2);

    es wird ein substr gebildet - in dem quasi die ganzen 300KB kopiert werden, und dieser wird dann wieder in rtrn kopiert - und dieser wird by value zurueck gegeben, also nochmal kopiert.

    wie du siehst wird bei dir _sehr_ viel kopiert. vorallem wenn der string lang wird, zB 300KB oder mehr - denn es wird dann ja immer alles kopiert (exponentiell)

    dagegen ist volkards version ideal - da wird nur das noetigste kopiert und nie der ganze string (es wird immer nur hinten angehaengt)



  • @ Shade Of Mine:
    Ok, das leuchtet mir ein. Ich habe das vorher nie so gesehen. Ich dachte immer der Operator += ist nur für schreibfaule ;-). Das der wirklich was anderes macht, hätte ich nicht gedacht.

    @ Stefan:
    Bisher lasse ich den eigentlich nur in einem Edit-Feld anzeigen.

    CU
    Konstantin



  • Original erstellt von Shade Of Mine:
    wie du siehst wird bei dir _sehr_ viel kopiert. vorallem wenn der string lang wird, zB 300KB oder mehr - denn es wird dann ja immer alles kopiert (exponentiell)

    warnung: beindruckendes fachwort erwürfelt. kunde muss neu bewertet werden.



  • Original erstellt von volkard:
    warnung: beindruckendes fachwort erwürfelt. kunde muss neu bewertet werden.

    hab ich was falsches geschrieben?

    wenn ja, dann bitte aufklären und mich nicht so verwirren...



  • exponentiell



  • Hi Community!

    Der folgende Code hat keine nennenswerte Optimierung gebracht:

    string read_file(const string &path)
    {
        string buf;
        string rtrn = "";
        ifstream ifs;
    
        ifs.open(path.c_str(), ios::in);
        if(ifs.fail())
        {
            return "";
        }
        MessageBox(NULL, TEXT ("Anfang!"), "Überschrift", NULL);
        while(!ifs.eof())
        {
            getline(ifs, buf);
            rtrn += buf;
            if(!ifs.eof())
                rtrn += "
    ";
        }
        MessageBox(NULL, TEXT ("Ende!"), "Überschrift", NULL);
    
        return rtrn;
    }
    

    Dann hab ich das mal so ausprobiert:

    string read_file(const string &path)
    {
        ifstream ifs;
    
        ifs.open(path.c_str(), ios::in);
        if(ifs.fail())
        {
            return "";
        }
    
        istreambuf_iterator<char> beg(ifs), end;
        string rtrn(beg, end);
    
        return rtrn;
    }
    

    Da bekam ich folgende Fehlermeldung:

    Error file.cpp 25: Could not find a match for 'std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string(std::istreambuf_iterator<char,std::char_traits<char> >,std::istreambuf_iterator<char,std::char_traits<char> >)' in function read_file(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > &)

    Fehlt mir da vielleicht eine Headerdatei?

    CU Konstantin



  • Kann mir da keiner was zu sagen, oder seit ihr alle über das verlängerte WE weg?



  • der Konstruktor geht da nich. und da die länge der datei nicht bekannt ist auch kein copy(). sag mal, wie du die datei brauchst. da wäre wohl eine besonderererere lösung nötig (ich denke an blockweise einlesen und dann - falls nötig - auf einen streich zusammenkleben)



  • Schau doch mal in die FAQ, da gibts ein ganzes Kapitel über ströme und Dateien.

    Devil



  • @ Mr. N
    In der Datei steht eine eMail nach RFC 822. Diese würde ich gerne in einen String inlesen, um sie dort weiter zu verarbeiten. (Header auslesen, MIME-Parts darstellen etc.) Letzendlich will ich das in eine Klasse kapseln.

    @ devil81
    Das Kapitel in der FAQ hab ich natürlich schon gelesen. Ich habe aber auf deinen Hinweis noch mal reingeschaut. Das einzige, was vielleicht interessant sein könnte, ist folgender Code-Schnippsel:

    using namespace std;
    ifstream FileIn("Main.cpp");
    if (FileIn)     // Falls FileIn gültig ist.
    {
        vector<string> Contents;              // Container für die einzelnen Zeilen
    
        // Solange kein Fehler auftritt und nicht eof
        for (string ReadString; getline(FileIn, ReadString); )         
            Contents.push_back(ReadString);   // Aktuelle Zeile in den Vektor einfügen
    
        // Alle Elemente des Vektors ausgeben.
        ostream_iterator<string> Out(cout, "\n");
        copy(Contents.begin(), Contents.end(), Out);
    }
    

    Ich muss zugeben, dass ich in Vektoren nicht so fit bin. Darum die Frage, ob mir das helfen könnte? Kann ich das vielleicht in einen String umwandeln? Bringt das überhaupt Geschwindigkeitsvorteile? Dann würde ich mich ein bischen damit beschäftigen...

    Man muss eine Datei doch irgenwie in einem vernünftigen Tempo einlesen können? Andere Programme schaffen das doch auch!

    Thx für Hilfe und Anregungen...

    CU
    Konstantin



  • Nein, ein Vektor ist quasi so eine Art virtuelles Array, in dem Vektor steht
    nun jede Zeile als String.

    Devil



  • Original erstellt von Konstantin:
    **

    using namespace std;
    ifstream FileIn("Main.cpp");
    if (FileIn)     // Falls FileIn gültig ist.
    {
        string FullText;
    
        for (string ReadString; getline(FileIn, ReadString); )         
            FullText += ReadString;           
    }
    

    **

    In FullText steht jetzt alles drin, nur ohne Newlines.
    Wenn du willst kannst du ja noch ein \n in der For-Schleife an FullText dranhängen.



  • Na gut, das hatte ich schon verstanden. Aber möchte die Datei doch gerne in _einen_ String haben. Das _muss_ doch irgenwie gehen? Bei einem Texteditor ist der Inhalt der Datei doch auch sofort angezeigt!

    CU
    Konstatin

    PS: Das versteh ich echt nicht, wieso das bei mir so lange dauert...



  • Habe mit folgendem Code eine 350 kb Datei eingelesen. Das einlesen dauert ca. 0.05 sec.Warum soll es dann bei dir so lange (30 sec) dauern ?
    Da muß wohl irgendwas anderes faul sein ...

    int main()
    {
       ifstream in;
       string buf,datei="";
       in.open("Text.txt");
       while(!in.eof())
       {
          getline(in,buf);
          datei+=buf;
       }
       in.close();
       cout << datei;
       return 0;
    }
    


  • Liest vielleicht von Diskette 😉



  • ...oder er kompiliert mal die Releaseversion.

    Devil



  • was mir noch einfaellt: du solltest vielleicht den Funktions-rueckgabewert nicht by-value machen, sonst wird der ganze String (also 300 Kb) nochmal kopiert....



  • Das kann aber alles niemals so lange dauern, selbst wenn ich 1000 mal 300 kb ine einen string kopiere, dauert das keine 30 sec.



  • Original erstellt von Blue-Tiger:
    was mir noch einfaellt: du solltest vielleicht den Funktions-rueckgabewert nicht by-value machen, sonst wird der ganze String (also 300 Kb) nochmal kopiert....

    es sei denn, der compiler beherrscht named return value optimization



  • @Winn:
    Nein, ich lese von Festplatte.

    @devil81:

    ...oder er kompiliert mal die Releaseversion.

    Hm, da bin ich jetzt überfragt. Wie kompiliert man denn nur die Releaseversion?

    @<Stefan>:
    Das versteh ich ja auch nicht... Ich hab ja extra MsgBoxen eingefügt, um zu sehen, ob das Problem wirklich beim einlesen besteht. Es ist wirklich die Schleife, die so lange dauert.
    Wenn ich gleich zu Hause bin, werde ich deinen Code noch mal nehmen und die Zeit mitstoppen lassen. Das Ergebnis werde ich euch dann mitteilen.

    Cu & Thx
    Konstantin


Anmelden zum Antworten