Autor |
Beitrag |
mega
      
Beiträge: 46
Win XP
D3 Prof
|
Verfasst: Do 04.05.06 23:17
Hallo, gibt es eine bessere Methode als folgende, um eine Datei in ein Memo zu laden?
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| while not EOF(Inputfile) do begin readln(Inputfile,S); Memo1.Lines.add(S); i := i + 1; end; |
Das ganze dauert bei großen Dateien (42 MB, 600000 Zeilen) extrem lange.
Und gibt es eine Möglichkeit, in bestimmten Zeitabständen Application.Processmessages aufzurufen? Das ganze soll nicht in jedem Schleifendurchlauf passieren. Mit Timer geht es nicht, der passiert nicht, solange die Schleife läuft.
Moderiert von raziel: Delphi-Tags hinzugefügtModeriert von raziel: Topic aus Sonstiges (Delphi) verschoben am Fr 05.05.2006 um 07:39
|
|
alias5000
      
Beiträge: 2145
WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
|
Verfasst: Do 04.05.06 23:28
Spontaner Tipp:
Verscuh mal, ein TidAntiFreeze auf die Form zu legen und die Property mit dem Namen OnlyWhenIdle oder so auf false zu legen.
Ansonsten wirst du wahrscheinlich nichts in der Art finden. Du könntest Threadgesteuert einen Progressdialog anzeigen, oder den Cursor verändert (crHourGlass).
Gruß alias5000
_________________ Programmers never die, they just GOSUB without RETURN
|
|
Ironwulf
      
Beiträge: 733
Erhaltene Danke: 2
|
Verfasst: Fr 05.05.06 00:09
vllt hilft dir ja das?
Delphi-Quelltext 1:
| Memo1.Lines.LoadFromFile(); |
|
|
alias5000
      
Beiträge: 2145
WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
|
Verfasst: Fr 05.05.06 01:20
Aso, halt, hab dein Post nicht richtig gelesen, sorry. Warum soll das in der SChleife nicht funktionieren? Du kannst ja alle 200 Durchgänge oder so mal processmessages aufrufen lassen
Delphi-Quelltext 1: 2: 3: 4:
| if i mod 200 = 0 then application.processmessages; |
_________________ Programmers never die, they just GOSUB without RETURN
|
|
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Fr 05.05.06 06:31
Mhm, wenn er ein bisschen auf Performance gehen will, ist das keine alzu gute Lösung, da mod relativ langsam ist.
Nimm des wegen lieber das hier:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| a:=200; if i=a then begin Application.ProcessMessages; inc(a, 200); end; |
Und statt eine File-Of-Konstruktion empfehle ich dir Streams, da diese am schnellsten unter Win sind, auch wenn es ggf. ein bisschen mehr Aufwand ist.
mfg
Heiko
|
|
jasocul
      
Beiträge: 6393
Erhaltene Danke: 147
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Fr 05.05.06 07:59
Wenn es um Performance geht ist Application.ProcesMessages so ziemlich das Dümmste, was man machen kann.
Schneller werden die Daten über einen Stream oder mit LoadFromFile (siehe Beitrag von Ironwulf) eingelesen.
Du musst dich nur entscheiden, was du willst. Entweder schnell, dafür friert das Programm kurz ein, oder langsam, aber mit Rückmeldung an den Anwender.
Ich würde die schnelle Variante bevorzugen. Man kann dem Anwender ja eine Nachricht anzeigen, dass das Laden der Datei einen Moment dauern kann.
|
|
MrSaint
      
Beiträge: 1033
Erhaltene Danke: 1
WinXP Pro SP2
Delphi 6 Prof.
|
Verfasst: Fr 05.05.06 09:56
Heiko hat folgendes geschrieben: | da mod relativ langsam ist. |
Stimmt nicht! mod ist eigentlich sogar ziemlich schnell, weil es direkt vom Prozessor unterstützt wird  (Ich hoffe jetzt nur, dass der Delphi-Compiler das auch so übersetzt, aber ich geh schon mal davon aus  ). Dein ProcessMessages ist viel viel langsamer (aber das hat jasocul ja schon gesagt
Ich würde auch die schnelle Methode benutzen. Threading bringt hier wahrscheinlich nichts, da der Thread ja dann mit der VCL "kommunizieren" würde und man Synchronize bräuchte.
MrSaint
_________________ "people knew how to write small, efficient programs [...], a skill that has subsequently been lost"
Andrew S. Tanenbaum - Modern Operating Systems
|
|
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Fr 05.05.06 15:50
|
|
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Fr 05.05.06 16:16
So habs mal gerade getestet:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| procedure TForm1.Button1Click(Sender: TObject); var i, j: integer; ST, T1, T2: Integer; k: integer; begin k:=0; ST:=GetCurrentTime; j:=0; for i:=0 to 10000000 do begin if j=i then begin inc(j, 200); inc(k); end; end; T1:=GetCurrentTime-ST;
k:=0; ST:=GetCurrentTime; j:=200; for i:=0 to 10000000 do begin if i mod 200=0 then begin inc(k) end; end; T2:=GetCurrentTime-ST; ShowMessage(IntToStr(T1)+#13+ IntToStr(T2)); end; |
Ergebnis: 15 ms und 125 ms.
Meine Variante ist also schneller  .
|
|
mega 
      
Beiträge: 46
Win XP
D3 Prof
|
Verfasst: So 07.05.06 21:25
Ironwulf hat folgendes geschrieben: | vllt hilft dir ja das?
Delphi-Quelltext 1:
| Memo1.Lines.LoadFromFile(); | |
Das geht nicht.
Inkompatible Typen String und Text.
|
|
Ironwulf
      
Beiträge: 733
Erhaltene Danke: 2
|
Verfasst: So 07.05.06 21:35
was schreibst du denn in dei klammern bei LoadFromFile?
|
|
mega 
      
Beiträge: 46
Win XP
D3 Prof
|
Verfasst: So 07.05.06 22:18
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| var InputFile: TextFile; OutputFile: TextFile;
procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then begin AssignFile(InputFile, OpenDialog1.Filename); Reset(InputFile);
Memo1.Clear; Memo2.Clear;
Memo1.Lines.LoadFromFile(InputFile);
CloseFile(InputFile); Memo1.Lines.add(''); end; end; |
Moderiert von Gausi: Delphi-Tags hinzugefügt
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: So 07.05.06 22:21
_________________ We are, we were and will not be.
|
|
mega 
      
Beiträge: 46
Win XP
D3 Prof
|
Verfasst: So 07.05.06 22:29
Gausi hat folgendes geschrieben: | Nee...das geht einfacher
|
Es kompiliert.
Funktioniert aber nicht.
Dann hat der ein Problem, die Datei zu lesen. Ist der gleiche Fehler wie nach meiner Methode, wenn man das reset() weglässt.
Reset geht nur mit InputFile, nicht mit OpenDialog1.Filename
Wichtiger wäre noch das Problem, wie man das Memo wieder gepspeichert bekommt. Der User kann durch den fileSave Dialog eine vorhandene oder neue Datei wählen können.
Bisher gehts nur mit einer schon vorhandenen Datei.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TForm1.Button2Click(Sender: TObject); begin if SaveDialog1.Execute then begin AssignFile(OutputFile, SaveDialog1.Filename); rewrite(OutputFile);
for i := 0 to Memo2.Lines.Count do begin writeln(OutputFile,Memo2.Lines[i]); end; CloseFile(Outputfile); end;
end; |
|
|
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Mo 08.05.06 06:57
mega hat folgendes geschrieben: | Dann hat der ein Problem, die Datei zu lesen. Ist der gleiche Fehler wie nach meiner Methode, wenn man das reset() weglässt. |
Was meckert er denn?
Speichern geht mit Memo1.Lines.SaveToFile

|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mo 08.05.06 08:34
Ich glaube, du hast da ein Verständnisproblem und schmeißt da was durcheinander...
Die Sachen wie Reset und Assign gehen mit Dateien. Opendialog1.Filename ist keine Datei, sondern ein Dateiname (also ein String). Die Funktionen LoadfromFile bzw. SaveToFile erwarten als Parameter keine Datei, sondern einen Dateinamen.
Was passiert, wenn man damit eine Datei schreiben will (durch Angabe des Namens), die vorher mit Reset o.ä. geöffnet wurde, weiß ich nicht - wahrscheinlich meckert er deswegen rum.
Oder: iirc hat TMemo eine Beschränkung, was die Textlänge angeht. Probier mal, kleinere Dateien zu laden. Wenn das klappt, liegt der Fehler dort, ansonsten noch bei dir 
_________________ We are, we were and will not be.
|
|
jasocul
      
Beiträge: 6393
Erhaltene Danke: 147
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Mo 08.05.06 08:50
|
|
mega 
      
Beiträge: 46
Win XP
D3 Prof
|
Verfasst: Mo 08.05.06 19:06
Jetzt gehts.
Es war noch ein nicht auskommentiertes AssignFile drin.
Das Ding ist so richtig schnell trotz 42 MB.
|
|