Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Lesen aus dem File,welcher Fall ist effinzienter?


buSC - Mi 10.03.10 11:35
Titel: Lesen aus dem File,welcher Fall ist effinzienter?
hallo liebe Forumer,
die elements von einem m*n array sind in einem untyped file gespeichert
worden. ich will in einer for schleife jeweils die Zeilen des Arrays
verarbeiten. ich habe zwei moeglichkeiten ausgedacht.
welcher Fall ist effizienter:
(bei meinem Fall: n und m<200 )

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:
numRead:integer;
f:  file;
mat:array of array of double;
zeile:array of double;
assignfile(f,'myfile');
j:=0;
setlength(mat,m,n);
reset(f, 8 ); 
//-------------------
//erste Fall: //erstmal alle elemente des Array in einem matrix speichern und dann verarbeiten
while not eof(f) do
    begin
       seek(f,n*j);
       BlockRead(f,mat[j,0],n,numRead);
       inc(j);
    end;
//dann der Prozess auf jeder arrayzeile in einer getrennten schleife:
for i:=0 to m-1 do
begin { prozess auf mat[i] } end;
//--------------
//zwite Fall //direktes lesen einer zeile von File und gleichzeitiger Prozess darauf"
while not eof(f)
  begin
    seek(f,n*j);
    BlockRead(f,zeile[0],n,numRead);
    //prozess auf array "Zeile"  
  end;
CloseFile(f);

Danke im Voraus. :)

Moderiert von user profile iconGausi: Delphi-Tags hinzugefügt


Gausi - Mi 10.03.10 11:52

Ich glaube, so ein ähnliches Topic hatten wir vor kurzem schonmal.

Hier ist das glaube ich völlig egal. Der Flaschenhals sind die Dateioperationen selbst, denke ich. Es wäre wahrscheinlich besser, wenn man die Datei in einem Rutsch lesen könnte. Also Datei in einen MemoryStream laden, und aus diesem dann (mit Methode 2) die einzelnen Zeilen rauslesen und verarbeiten.


Gammatester - Mi 10.03.10 16:55

Bevor Du Dir Sorgen um die Effizienz machst, solltest Du darauf achten, daß der Code richtig ist, getreu dem Grundsatz "Erst richtig implementieren, dann optimieren". In den Anweisungen

Delphi-Quelltext
1:
2:
3:
BlockRead(f,mat[j,0],n,numRead);
//bzw
BlockRead(f,zeile[0],n,numRead);
liest Du jeweils n Bytes. Das gibt zwar keine Fehler, aber Deine Ergebnisse sind garantiert falsch. Die richtige Anzahl wäre

Delphi-Quelltext
1:
BlockRead(f,mat[j,0],n*sizeof(Double),numRead);                    


buSC - Sa 13.03.10 18:10

danke an alle freunde ,fuer ihre Antworte,
aber an Gammatester: ich glaube nicht dass die Antwort falsh ist,weil ich den befehl "reset(f, 8 )" benutuz habe und das sagt ,das die daten 8 byte double sind oder ?


alzaimar - Sa 13.03.10 19:39

user profile iconbuSC hat folgendes geschrieben Zum zitierten Posting springen:
..."reset(f, 8 )"...

Schreib lieber

Delphi-Quelltext
1:
reset (f, SizeOf (Double));                    

Das ist aussagekräftiger.
user profile iconGammatester hat folgendes geschrieben Zum zitierten Posting springen:
...getreu dem Grundsatz "Erst richtig implementieren, dann optimieren".

Erst richtig lesen, dann posten. :mrgreen:


BenBE - Mi 17.03.10 22:19

Mal ganz davon abgesehen, dass die alten Pascal-Funktionen für Dateihandling schon seit mehreren Versionen nicht mehr verwendet werden sollten und stattdessen durch Streams ausgetauscht gehören.

Und um's generell zu sagen: Große Datenblöcke zusammenhängend lesen und dann aus dem Speicher zusammenhängend bearbeiten. Jeder Dateisystemzugriff ist unnötiger Overhead, selbst wenn er aus einem Cache bedient wird.


jaenicke - Do 18.03.10 01:11

Ich habe zu diesem Zweck MMFs benutzt. Dabei muss man dann nur darauf achten die Blockgröße und Position in Abhängigkeit von der Datenmenge insgesamt klug zu setzen. Insgesamt habe ich auf diese Weise ca. 30-50 Millionen Zeichen pro Sekunde aus einer Datei auslesen und parsen können. Das heißt trotz zeichenweisem Zugriff bin ich relativ weit an die Maximalgeschwindigkeit der Festplatte herangekommen.


alzaimar - Do 18.03.10 08:24

Hi jaenicke,

hättest Du nicht Lust, dieses Verfahren in einem getrennten Thread zu erläutern?


jaenicke - Do 18.03.10 15:52

Mal schauen im Grunde ist es sehr einfach und nur wenig Code. Anschauen lässt es sich schon einmal hier (unter Source\Units\FileAccessUtils.pas), vielleicht hilft es ja für das aktuelle Problem auch:
http://www.delphi-forum.de/viewtopic.php?t=93084
In dem Projekt benutze ich das so dass ich den kompletten Zweig HKLM aus einer exportierten Registry-Datei von 350 MiB in weniger als 10 Sekunden eingelesen und angezeigt bekomme. ;-)