Autor Beitrag
mega
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Win XP
D3 Prof
BeitragVerfasst: Do 04.05.06 23:17 
Hallo, gibt es eine bessere Methode als folgende, um eine Datei in ein Memo zu laden?

ausblenden 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 user profile iconraziel: Delphi-Tags hinzugefügt
Moderiert von user profile iconraziel: Topic aus Sonstiges (Delphi) verschoben am Fr 05.05.2006 um 07:39
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
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)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 733
Erhaltene Danke: 2



BeitragVerfasst: Fr 05.05.06 00:09 
vllt hilft dir ja das?

ausblenden Delphi-Quelltext
1:
Memo1.Lines.LoadFromFile();					
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
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)
BeitragVerfasst: 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
ausblenden Delphi-Quelltext
1:
2:
3:
4:
//in der Schleife...
if i mod 200 = 0 then
  application.processmessages;
//usw.

_________________
Programmers never die, they just GOSUB without RETURN
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: 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:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
a:=200;
if i=a then
begin
  Application.ProcessMessages;
  inc(a, 200);
end;
//hier den "eigentlichen" Code


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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: 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 user profile iconIronwulf) 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1033
Erhaltene Danke: 1

WinXP Pro SP2
Delphi 6 Prof.
BeitragVerfasst: Fr 05.05.06 09:56 
user profile iconHeiko 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Fr 05.05.06 15:50 
user profile iconMrSaint hat folgendes geschrieben:
user profile iconHeiko 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 ;)


Das Application.ProcessMessages lahmarschig ist weiß ich, des wegen sollte es auch nicht ständig aufgerufen werden. Aber soweit ich weiß, ist mod trotzdem langsamer als die Variante, die ich hier gepostet habe (nach meinen Erfahrungen).

Ich werde ggf. noch einmal Testreihen durchführen bzw. mir den ASM-Code mal angucken ;).
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Fr 05.05.06 16:16 
So habs mal gerade getestet:

ausblenden volle Höhe Delphi-Quelltext
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 :P.
mega Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Win XP
D3 Prof
BeitragVerfasst: So 07.05.06 21:25 
user profile iconIronwulf hat folgendes geschrieben:
vllt hilft dir ja das?

ausblenden Delphi-Quelltext
1:
Memo1.Lines.LoadFromFile();					

Das geht nicht.

Inkompatible Typen String und Text.
Ironwulf
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 733
Erhaltene Danke: 2



BeitragVerfasst: So 07.05.06 21:35 
was schreibst du denn in dei klammern bei LoadFromFile?
mega Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Win XP
D3 Prof
BeitragVerfasst: So 07.05.06 22:18 
ausblenden 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 user profile iconGausi: Delphi-Tags hinzugefügt
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: So 07.05.06 22:21 
Nee...das geht einfacher ;-)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TForm1.Button1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
  begin
    Memo1.Clear;
    Memo2.Clear;
    Memo1.Lines.LoadFromFile(OpenDialog1.Filename);
    Memo1.Lines.add('');
  end;
end;

_________________
We are, we were and will not be.
mega Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Win XP
D3 Prof
BeitragVerfasst: So 07.05.06 22:29 
user profile iconGausi 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.
ausblenden 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;
//Memo2.Lines.SaveToFile(SaveDialog1.Filename);
CloseFile(Outputfile);
end;

end;
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Mo 08.05.06 06:57 
user profile iconmega 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mo 08.05.06 08:34 
Ich glaube, du hast da ein Verständnisproblem und schmeißt da was durcheinander... :gruebel:

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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mo 08.05.06 08:50 
user profile iconGausi hat folgendes geschrieben:
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 ;-)

Wenn ich das richtig in Erinnerung habe, gibt es für jeden Zeileneintrag einen Zeiger von 4 Byte. Das entspricht 2^32 Zeilen. Bei 10 Zeichen pro Zeile wären wir ca 40GB. Ich glaube, da macht eher die Auslagerungsdatei ein Problem. :mrgreen:
mega Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 46

Win XP
D3 Prof
BeitragVerfasst: 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.