Programm unglaublich langsam



  • In dem Text sind jede menge \n\r das ist hauptsächlich das Problem, denn die Daten stammen nicht von mir.

    Es müssen später noch mehr Werte in die Tabelle, die genau so angeordnet sind. Später sollen die Daten dann per AddRow hinzugefügt werden, eben an die passende stelle. Das mit isctrl werde ich ausprobieren.

    EDIT: isctrl kann ich nicht finden, auch wenn ich die Header dazu einbau. Ok, habs jetzt, heißt iscntrl. Die Hilfe findet auch nichts. ProcessMessage brauch ich, weil die GUI beil laden neu gezeichnet werden soll.

    EDIT2: Also, ich hab jetzt die Chars mit iscntrl aussortiert. Dann hab ich SetRow rausgenommen. ProcessMessages hab ich jetzt nur noch im Aufruf von AddRow. Allerdings dauerts immernoch ca 8 Sekunden bis ein Datensatz angezeigt wird... 😡



  • TStringList* dat = new TStringList();
       //Datei in StringList laden
       dat->LoadFromFile("dat.txt");
       //\n und \r im gesammten Text entfernen
       dat->Text=StringReplace(dat->Text,"\n","",TReplaceFlags() << rfReplaceAll);
       dat->Text=StringReplace(dat->Text,"\r","",TReplaceFlags() << rfReplaceAll);
       //Delimiter setzen (#)
       dat->Delimiter = '#';
       dat->DelimitedText = dat->Text;
       //Anzahl der Rows berechnen (Anzahl Einträge in Liste / 2 Spalten)
       StringGrid1->RowCount = dat->Count / 2;
       //Daten ins Grid schreiben
       for(int i=0;i<dat->Count-1;i+=2)
       {
          StringGrid1->Cells[0][i/2]=dat->Strings [i];
          StringGrid1->Cells[1][i/2]=dat->Strings [i+1];
       }
       delete dat;
    


  • Allerdings würde ich bei extrem großen Dateien dazu neigen, nicht alles ins Grid zu schreiben, sondern nur den sichtbaren Teil (meinetwegen 20-30 Zeilen).
    Dann baust du dir eine Funktion mit der du dann durch die Daten scrollst.



  • also, ich hab deinen Code jetzt gerade getestet, das Laden läuft jetzt schon 5 Minuten CPU Zeit und ist noch nicht beim Einfügen der Daten in die Tabelle.

    So, nach 5:30 Waren die Daten dann geladen und angezeigt, allerdings ist jedes Wort in einer eigenen Zeile, bzw. immer zwei Wörter nebeneinander.

    Es hilft ja auhc nix, denn das laden der Daten dauert so lange, es dauert keine 30 Sekunden die Daten ins StringGrid zu kopieren.

    http://s3.bilder-hosting.de/tbnl/LKDW4.jpg



  • Es hilft ja auhc nix, denn das laden der Daten dauert so lange

    Das laden einer 500 kb Datei dauert bei mir keine Sekunde.



  • So, nach 5:30 Waren die Daten dann geladen und angezeigt, allerdings ist jedes Wort in einer eigenen Zeile, bzw. immer zwei Wörter nebeneinander.

    Eine 600 kb Datei hat bei mir ca 4-5 Sekunden gebraucht, bis alles angezeigt wurde.



  • 😞 kann ich dir mal meine Datei zuschicken und du testest es damit?



  • Kannst du die Datei irgendwo hochladen ? Da ich nur ungern meine email Adressen irgendwo hinterlasse. (Hab schon genug Spam).





  • versuch mal folgendes

    #include <fstream>
    #include <string>
    
    using namespace std;
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    string iBuf;
    AnsiString iBuffer;
    ifstream inf("d:\\test.txt");
    getline(inf, iBuf);
    getline(inf, iBuf);
    int i=1, k;
    while ( !inf.eof() )
    	{
    	iBuf = "";
    	getline(inf, iBuf, '#');
    	iBuffer = iBuf.c_str();
    	iBuffer = StringReplace(iBuffer,"\n","",TReplaceFlags() << rfReplaceAll);
    	iBuffer = StringReplace(iBuffer,"\r","",TReplaceFlags() << rfReplaceAll);
    	if (TryStrToInt(iBuffer, k))
    		StringGrid1->Cells[0][i]=iBuffer;
    	else
    		{
    		StringGrid1->Cells[1][i]=iBuffer;
    		i++;
    		}
    	}
    StringGrid1->RowCount = i;
    inf.close();
    }
    

    noch ein Hinweis: bei StringList->Delimiter wird nicht nur der angegebene Delimiter sondern auch jedes Leerzeichen als Delimiter verwendet, daher kamen die Wörter alle einzeln

    [Edit] die Sonderbehandlung der Kommentare mußt du natürlich noch machen



  • bei deimem code zeigt er nur 501 an. also nur die erste zahl.



  • meinst du so ?

    ifstream in("dat.txt");
       string buff;
       String ansibuff;
       short pos=0;
       while(!in.eof())
       {
          getline(in,buff,'#');
          ansibuff=buff.c_str();
          ansibuff=StringReplace(ansibuff,"\r","",TReplaceFlags() << rfReplaceAll);
          ansibuff=StringReplace(ansibuff,"\n","",TReplaceFlags() << rfReplaceAll);
          StringGrid1->Cells [pos][StringGrid1->RowCount-1]=ansibuff;
          pos++;
          if(pos>1)
          {
             StringGrid1->RowCount++;
             pos=0;
          }
       }
       in.close();
    


  • Hallo,

    Sehe ich das richtig, das es um das entfernen der Zeilenumbrüche geht und das das so lange dauert... wenn ja, versuch mal das hier :

    //Datei in StringList laden
    dat->LoadFromFile("test.txt");
    //\n und \r im gesammten Text entfernen
    AnsiString NeuerText = "";
    for (int i = 0; i < dat->Count; i++)
      NeuerText += dat->Strings[i];
    

    Das geht um Längen schneller als StringReplace.

    Ich weiss ja nun auch nicht wie das Ergebnis (im StringGrid) aussehen soll, aber evtl. so ?

    TStringList* dat = new TStringList();
    AnsiString NeuerText  = "";
    AnsiString NeuerText2 = "";
    // Datei in StringList laden
    dat->LoadFromFile("test.txt");
    // \r\n im gesammten Text entfernen
    for (int i = 0; i < dat->Count; i++)
     NeuerText += dat->Strings[i];
    //Delimiter setzen (#)
    for (int i = 1; i <= NeuerText.Length(); i++)
    {
     if (NeuerText[i] == '#')
       NeuerText2 += "\r\n";
     else
       NeuerText2 += NeuerText[i];
    }  // for (int i = 1; i <= NeuerText.Length(); i++)
    dat->Text = NeuerText2;
    //Anzahl der Rows berechnen (Anzahl Einträge in Liste / 2 Spalten)
    StringGrid1->RowCount = dat->Count / 2;
    //Daten ins Grid schreiben
    for(int i = 0; i < dat->Count - 1; i += 2)
    {
      StringGrid1->Cells[0][i/2]=dat->Strings [i];
      StringGrid1->Cells[1][i/2]=dat->Strings [i+1];
    }  // for(int i = 0; i < dat->Count - 1; i += 2)
    // Das kann später raus, ist nur zum Testen...
    dat->SaveToFile(ExtractFilePath(Application->ExeName) + "neu.txt");
    delete dat;
    

    Das Grid wird dabei in weniger als einer Sekunde geladen...

    Nash



  • ifstream in("test.txt");
    string buff="";
    String ansibuff;
    unsigned i=0;
    short pos=1;
    while(!in.eof())
    {
       getline(in,buff,'#');
       ansibuff=buff.c_str();
       ansibuff=StringReplace(ansibuff,"\r","",TReplaceFlags() <<rfReplaceAll);
       StringGrid1->Cells [pos=!pos][i++/2]=StringReplace(ansibuff,"\n","",TReplaceFlags() <<rfReplaceAll);
    }
    StringGrid1->RowCount = i/2;
    in.close();
    

    Etwas optimiert gehts dann in unter ner halben Sekunde.



  • Ich habe mal Versuchsweise den Code von Nash probiert.
    Funktioniert beim ersten Durchlauf einwandfrei.
    Aber wenn man das mehrmals durchläuft (Hab es dazu mal ins OnClick eines Buttons gesetzt) dann wird es bei mir elendig langsam.
    Nur ich begreife nicht wieso. Hat da jemand ne Erklärung.



  • Ich komme jetzt gerade nicht an den Code (liegt aufem Arbeitsrechner) werde mir das Montag morgen nochmal anschauen.



  • Hallo,

    @ frage_zum_Code :
    Nimm den Code von "holg_er", der is besser...

    Nash



  • Nash schrieb:

    Hallo,

    @ frage_zum_Code :
    Nimm den Code von "holg_er", der is besser...

    Nash

    Aber ich würde gerne verstehen, warum der Code beim zweiten... Durchlauf immer langsamer wird.
    Die StringList wird doch danach komplett wieder mit delete gelöscht. 😕



  • Hallo,

    So wird er nicht langsamer, ist aber immer noch nicht so schnell wie der andere. Man könnte da immer noch was optimieren...

    // Datei in StringList laden
    AnsiString NeuerText  = "";
    AnsiString Zeile      = "";
    TStringList *dat = new TStringList();
    dat->LoadFromFile("test.txt");
    for (int i = 0; i < dat->Count; i++)
      NeuerText += dat->Strings[i];
    dat->Clear();
    for (int i = 1; i <= NeuerText.Length(); i++)
    {
      if (NeuerText[i] == '#')
      {
        dat->Add(Zeile);
        Zeile = "";
      }  // if (NeuerText[i] == '#')
      else
        Zeile += NeuerText[i];
    }  // for (int i = 1; i <= NeuerText.Length(); i++)
    //Anzahl der Rows berechnen (Anzahl Einträge in Liste / 2 Spalten)
    StringGrid1->RowCount = dat->Count / 2;
    //Daten ins Grid schreiben
    for(int i = 0; i < dat->Count - 1; i += 2)
    {
      StringGrid1->Cells[0][i/2]=dat->Strings [i];
      StringGrid1->Cells[1][i/2]=dat->Strings [i+1];
    }  // for(int i = 0; i < dat->Count - 1; i += 2)
    dat->SaveToFile(ExtractFilePath(Application->ExeName) + "neu.txt");
    if (dat != NULL)
    {
      dat->Clear();
      delete dat;
      dat = NULL;
    }  // if (dat != NULL)
    

    Nash



  • danke, jetzt ist der code schell genug.


Anmelden zum Antworten