Delphi-PRAXiS
Seite 4 von 5   « Erste     234 5      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   TStringlist mit 60000 Einträgen zu langsam (https://www.delphipraxis.net/147517-tstringlist-mit-60000-eintraegen-zu-langsam.html)

Reinhard Kern 11. Feb 2010 15:25

Re: TStringlist mit 60000 Einträgen zu langsam
 
Zitat:

Zitat von Hawkeye219
Warum nimmst du eigentlich den Umweg über eine Stringliste? Am Ende fügst du ja doch wieder alles zu einem einzelnen String zusammen.

Hallo Hawkeye, das gleiche frage ich ja bezüglich der Eingangsdaten, aber das wird entweder niedergemacht oder ignoriert - statt einfach weitere Zeilen an den Ausgangsdatei anzuhängen (simples Schreiben in eine Datei), muss mit hundertausenden von stringreplace-Aufrufen dafür gesorgt werden, das das Ergebnis am Ende so aussieht, wie es ohne jeden Aufwand von vornherein hätte aussehen können.

Eine einfache readln - verarbeiten - writeln Sequenz ist zwar viel effektiver, aber verpönt.

Zitat:

Zitat von friedemann2009
@Reinhart, was meinst du damit?

Gruß, friedemann

Hallo Friedemann, wie du siehst, kann man das hier im Forum nicht besprechen, einfache und effektive Programme sind bei der überwiegenden Mehrheit absolut unerwünscht. Also vergiss es einfach.

Gruss Reinhard

himitsu 11. Feb 2010 15:54

Re: TStringlist mit 60000 Einträgen zu langsam
 
Zitat:

Zitat von Reinhard Kern
Hallo Friedemann, wie du siehst, kann man das hier im Forum nicht besprechen, einfache und effektive Programme sind bei der überwiegenden Mehrheit absolut unerwünscht. Also vergiss es einfach.

Ideal wäre es mal, OOP-mäßig eine neue Klasse zu erstellen, welche die Vorteile der "alten" Pascalfunktionen mit einigen Verbesserungen/Optimierungen vereint.
Also eine Art TStringStream, welchen man an alle möglichen Streams ranhängen kann.
Vorallem an TFileStream und TMemoryStream.

Ja, es gibt einen TStringStream, aber der ist ja wohl ein Witz.

Ideen dafür existieren schon länger, aber ich hatte nie einen Grund, dieses mal zu machen. :oops:


Ein großes Problem exisitert nämlich, denn mit den alten Pascal-Routinen kann man selbst ab D2009 nur ANSI-Dateien erstellen und auslesen.

Hawkeye219 11. Feb 2010 16:31

Re: TStringlist mit 60000 Einträgen zu langsam
 
Hallo,
Zitat:

Zitat von himitsu
Ideal wäre es mal, OOP-mäßig eine neue Klasse zu erstellen, welche die Vorteile der "alten" Pascalfunktionen mit einigen Verbesserungen/Optimierungen vereint.
Also eine Art TStringStream, welchen man an alle möglichen Streams ranhängen kann.
Vorallem an TFileStream und TMemoryStream.

auch wenn es dem TE aufgrund seiner eingesetzten Delphi-Version nicht hilft, passt es thematisch noch in diesen Thread:

TStreamReader/TStreamWriter
TStringReader/TStringWriter

Gruß Hawkeye

Reinhard Kern 11. Feb 2010 16:32

Re: TStringlist mit 60000 Einträgen zu langsam
 
Zitat:

Zitat von himitsu
Ein großes Problem exisitert nämlich, denn mit den alten Pascal-Routinen kann man selbst ab D2009 nur ANSI-Dateien erstellen und auslesen.

Falls das ein Problem ist oder wird, es soll auch unter Windows API Möglichkeiten geben, aus einer Datei zu lesen. Klassen für Textdateien bzw. eine Hierarchie davon habe ich mir auch schon erstellt, dabei habe ich teilweise auch eigene readln und writeln Prozeduren verwendet; das ist ja schliesslich kein Hexenwerk, das nur Borlandprogrammierer hinkriegen.

Gruss Reinhard

p80286 11. Feb 2010 16:39

Re: TStringlist mit 60000 Einträgen zu langsam
 
Hallo zusammen,
ist ja richtig was los hier.

wie ja schon mehrmals angemerkt wurde ist
Delphi-Quellcode:
function gibmirLemma(s:string; sep:char) :string;
var
  t: Tstringlist;  
begin
  //hier muss jetzt das zweite Wort rausgefiltert werden
  t:= tstringlist.create;
  try
    extractstrings([char(sep)], [' '], pchar(s), t);
    result:= t.Strings[2];
  finally
    t.free;
  end;
end;
nicht so optimal.

wie wäre denn z.B. so etwas:
Delphi-Quellcode:
function gibmirLemma(s:string; sep:char) :string;
var
  pp : integer;  
begin
  result:='';
  //hier muss jetzt das zweite Wort rausgefiltert werden
  pp:=pos(sep,s);
  if pp>0 then begin
    pp:=posex(sep,s,pp+1);
    if pp>0 then
      result:= copy(s,pp+1,255);
  end;
end;
@reinhard
Auch wenn ich Dir im Prinzip zustimme, TStringlist ist einfach genial, besonders wenn die Verarbeitung ein satz vor zwei Satz zurück, einen löschen läuft.

Wenn es wirklich nur darum geht (und das hab ich noch nicht erkannt) einen Satz nach dem anderen zu lesen, zu filetieren und dann wegzuschreiben/an einen String anzuhängen würde ich Dich inhaltlich voll unterstützen.

und verlier bitte den Unterschied nicht aus den Augen:

Delphi-Quellcode:
var
  sl=tstringlist;


sl:=tstringlist.create;
...
sl.loadfromfile('MeineDaten');
for i:=0 to sl.count-1 do
  irgendwas
sl.free;
Delphi-Quellcode:
var
  f     : textfile;
  buffer : array [0..8191] of byte;
  satz  : string


assign(f,'MeineDaten');
settextbuf(f,buffer,sizeof(buffer));
reset(f);
repeat
  readln(f,satz);
  machwwasmitsatz
unil eof(f);
closefile(f);
Die zweite Möglichkeit ist doch wesentlich aufwendiger.

Gruß
K-H

Chemiker 11. Feb 2010 19:11

Re: TStringlist mit 60000 Einträgen zu langsam
 
Hallo friedemann2009,

wie viel Speicher verbrauchst Du für die 100.000 Einträge?
Welches Windows ist auf dem Rechner installiert?

Die geringe Geschwindigkeit könnte auch von Windows verursacht werden, wenn zu viel Speicher belegt wird. Wenn der Speicher voll ist, fängt Windows an Teile davon auf die Festplatte auszulagern.

Bis bald Chemiker

David Martens 11. Feb 2010 23:11

Re: TStringlist mit 60000 Einträgen zu langsam
 
Hallo,
jetzt geb ich auch mal meinen Senf dazu.
Das was hier die meiste Zeit braucht sind doch die vielen gibmir... Aufrufe.

Hier wie ich es machen würde:
Delphi-Quellcode:
    begin
      quelle := tstringlist.create;
      ziel := tstringlist.create;
      eineZeile := tstringlist.create;
      try
        //Previewdatei laden
        quelle.LoadFromFile(extractfilepath(application.exename) + 'preview2.dat');

        eineZeile.Delimiter := #9;
        eineZeile.QuoteChar := '"'; // hier bin ich mir nicht sicher ob das reicht um die stringreplace überflüssig zu machen

        for i := 0 to quelle.Count - 1 do
        begin
          // vorsichtshalber säubern, muß aber nicht sein
          eineZeile.Clear;
          // nur 1 mal parsen (und das von Delphi selbst) statt x mal immerwieder
          // hier kann wahlweise auch mit readln gearbeitet werden wenn man will
          eineZeile.DelimitedText := quelle.Strings[i];

          //Token zusammennehmen
          if pos('#' + eineZeile[1] + '#', tok) <> 0 then
            ziel.text:= ziel.text + eineZeile[0];

          //Lemma zusammennehmen
          if pos('#' + eineZeile[1] + '#', lem) <> 0 then
            begin
              schon := 0;

              if eineZeile[2] in ['<UNKNOWN>', '@card@', 'CARD', '@ord@'] then
              begin
                if (eineZeile[2] = '<UNKNOWN>') then
                begin
                  if checkbox2.checked then
                  begin
                    ziel.text := ziel.text + eineZeile[0];
                    schon := 1;
                  end;
                end
                else // alle anderen
                begin
                  if checkbox4.checked then
                  begin
                    ziel.text := ziel.text + eineZeile[0];
                    schon := 1;
                  end;
                end;
              end;

              if schon = 0 then
                ziel.text := ziel.text + eineZeile[2];
            end;

          if pos('#' + eineZeile[1] + '#', poss) <> 0 then
            ziel.Text := ziel.text + eineZeile[1];
         end;

        for i := 0 to ziel.Count - 1 do
          zielende := zielende + ' ' + ziel.Strings[i];

        memo2.text := zielende;

      finally
        quelle.Free;
        ziel.Free;
        eineZeile.Free;
      end;
Damit wird nur 1 mal geparst und dann auf die Teile direkt zugegriffen.
Ob das jetzt 100 pro funktioniert kann ich aber nicht so aus dem Hut sagen.

Um zur Diskusion beizutragen: soweit ich mich erinnern kann nutzt LoadFromFile u.Ä. die Windows API für das eigentliche Ansprechen der Datei, während readln eine Delphi (besser Pascal) eigene Umsetzung der gleichen Funktion ist. An dieser Stelle lässt sich darüber streiten, ob die Windows eigene oder die Borland/CodeGear/Embarcadero umsetzung der selben schneller ist. Ich bin ja (auch wenn ich das sonst nicht so sehe) eher für MS, alleine durch die Tatsache das MS die Funktionen auf die jeweilige Windows Version anpassen kann und Delphi von der Plattform wo das Programm dann läuft zur Compiletime keine Ahnung haben kann.

Bis Dann, und hoffentlich konnte ich helfen,
David

Nachtrag: Ich hab nochmal zusammegerechnet, du zerpflückst jede Zeile 5 mal, da hast du dein Performanceproblem. Wenn es so wie in meinem Code nicht geht kannst du auch eine Funktion schreiben die alle 3 Teile auf einmal zurückgibt und dann im "Hauptprogramm" in 3 einzelne Variablen speichert. So in etwa:
Delphi-Quellcode:
procedure aufteilen(const s : string; const sep : char; var Token, wortart, Lemma : string);
var
  t: Tstringlist;
begin
  //hier muss jetzt das zweite Wort rausgefiltert werden
  t:= tstringlist.create;
  try
    extractstrings([char(sep)], [' '], pchar(s), t);
    Token  := t.Strings[0];
    wortart := t.Strings[1];
    Lemma  := t.Strings[2];
  finally
    t.free;
  end;
end;

// so wirds dann benutzt, einmal am Anfang
aufteilen(quelle.strings[ii], #9, token_Variable, wortarttemp, lemmareal);

jensw_2000 11. Feb 2010 23:35

Re: TStringlist mit 60000 Einträgen zu langsam
 
Eventuell tut es in diesem speziellen Fall auch schon
Delphi-Quellcode:
meineStringliste.sorted := true;
?

David Martens 11. Feb 2010 23:38

Re: TStringlist mit 60000 Einträgen zu langsam
 
Die Sortierung ist, glaube ich, schon wichtig. Mit .sorted := true; geht die verloren.

friedemann2009 12. Feb 2010 13:31

Re: TStringlist mit 60000 Einträgen zu langsam
 
Zitat:

Zitat von Chemiker
Hallo friedemann2009,

wie viel Speicher verbrauchst Du für die 100.000 Einträge?
Welches Windows ist auf dem Rechner installiert?

Die geringe Geschwindigkeit könnte auch von Windows verursacht werden, wenn zu viel Speicher belegt wird. Wenn der Speicher voll ist, fängt Windows an Teile davon auf die Festplatte auszulagern.

Bis bald Chemiker

Also wenn ich es richtig verfolge, wird nichts ausgelagert. Windoof XP prof. Ich fürchte auch, dass es an den "gibmir"-Funktionen und dem Replace liegt. Ich bin am Nachprobieren, was hier so bisher geschrieben wurde.

Danke und Gruß,
friedemann


NACHTRAG:

- Falls ich es noch nicht schrieb: Thanks a lot für die vielen Hinweise!


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:14 Uhr.
Seite 4 von 5   « Erste     234 5      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz