Dateizugriffe


Inhaltsverzeichnis:

Einführung
TextFile / Read
File / BlockRead
TFileStream
TFileStream / TReader (ab Delphi 3)


Einführung

Die Aufgabe ist es eine Datei zeichenweise zu lesen. Es gibt verschiedene Methoden das zu realisieren, ich habe hier 4 davon aufgeführt und dabei die Geschwindigkeiten verglichen.

Vorweg gleich die Zeiten in Sekunden, um 30 MByte zu lesen:

Methode Zeit
TextFile / Read 8,03
File / BlockRead 7,92
TFileStream 327,22
TFileStream / TReader 8,55

Rahmenbedingungen: Delphi 3.02 Professional, Programm außerhalb der IDE gestartet, 30MByte-Datei, Rechner: PII-300, Ultrawide-SCSI.

Allgemeine Deklarationen:
const
  BufferSize = 4096;
  TestFilename = 'C:\TestFile.txt';

zurück zum Inhaltsverzeichnis

TextFile / Read

Die Methode mit Read funktioniert eigentlich am besten, man sollte jedoch beim Erzeugen einen großen Puffer anlegen.
Wichtig ist, daß Buffer solange zur Verfügung steht, bis CloseFile aufgerufen wird.

function Methode1:Integer;
var
  f : TextFile;
  Buffer : Pointer;
  Ch : Char;
  i : Integer;
begin
  Result:=0;
  GetMem(Buffer,BufferSize);
  try
    AssignFile(f,TestFilename);
    SetTextBuf(f,Buffer^,BufferSize);
    Reset(f);
    try
      while Not Eof(f) do begin
        Read(f,ch);
        Inc(Result);
      end;
    finally
      CloseFile(f);
    end;
  finally
    FreeMem(Buffer,BufferSize);
  end;
end;

zurück zum Inhaltsverzeichnis

File / BlockRead

Blockread ist ein ganz wenig schneller, der Programmieraufwand ist größer, da man sich hier selber um die Verwaltung des Puffers kümmern muß. (Pufferende prüfen, Dateiende prüfen, ...)

In BufferCount steht die Anzahl der wirklich gelesenen Bytes.

function Methode2:Integer;
type
  PBuffer = ^TBuffer;
  TBuffer = array[0..BufferSize-1] of Char;
var
  f : File;
  Buffer : PBuffer;
  BufferCount : Integer;
  BufferPos : Integer;

function Eof:Boolean;
begin
  if BufferPos>=BufferCount then begin { einlesen Puffer }
    BlockRead(f,Buffer^,BufferSize,BufferCount);
    BufferPos:=0;
  end;
  Result:=BufferCount=0;
end;

function Read:Char;
begin
  if Eof then raise Exception.Create('Dateiende erreicht');
  Result:=Buffer^[BufferPos];
  Inc(BufferPos);
end;

var
  i : Integer;
  Ch : Char;
begin
  Result:=0;
  GetMem(Buffer,BufferSize);
  try
    AssignFile(f,TestFilename);
    Reset(f,1);
    { Puffer initialisieren }
    BufferCount:=BufferSize;
    BufferPos:=BufferSize;
    try
      while Not Eof do begin
        Ch:=Read;
        Inc(Result);
      end;
    finally
      CloseFile(f);
    end;
  finally
    FreeMem(Buffer,BufferSize);
  end;
end;

zurück zum Inhaltsverzeichnis

TFileStream

FileStream alleine ist ziemlich uneffektiv, die Puffergröße ist hier von der Windows-API abhängig. Ergebnis 40-fache Zugriffszeit.

function Methode3:Integer;
var
  f : TFileStream;
  Ch : Char;
  i : Integer;
begin
  Result:=0;
  f:=TFileStream.Create(TestFilename,fmOpenRead);
  try
    for i:=0 to f.Size-1 do begin
      f.Read(Ch,SizeOf(Ch));
      Inc(Result);
    end;
  finally
    f.Free;
  end;
end;

zurück zum Inhaltsverzeichnis

TFileStream / TReader

TReader sorgt für einen gepufferten Zugriff. Es lassen sich beliebige Strukturen in beliebiger Reihenfolge lesen. Für sequentielle Nicht-Char Dateizugriffe eine ideale Lösung. Diese Methode ist nur wenig langsamer als Methode 1 und 2.

function Methode4:Integer;
var
  f : TFileStream;
  r : TReader;
  Ch : Char;
  i : Integer;
begin
  Result:=0;
  f:=TFileStream.Create(TestFilename,fmOpenRead);
  try
    r:=TReader.Create(f,BufferSize);
    try
      for i:=0 to f.Size-1 do begin
        r.Read(Ch,SizeOf(Ch));
        Inc(Result);
      end;
    finally
      r.Free;
    end;
  finally
    f.Free;
  end;
end;

zurück zum Inhaltsverzeichnis

Mails an mich unter webmaster@pjh2.de. Haftungsausschluss
Bitte keine E-Mails zu Delphi, die sich nicht auf diese Seiten beziehen. Sie werden von mir nicht beantwortet.