Thema: Delphi TBufferedFileStream

Einzelnen Beitrag anzeigen

Laufi

Registriert seit: 21. Mär 2006
86 Beiträge
 
#1

TBufferedFileStream

  Alt 14. Sep 2009, 15:16
Hallo!

Ich muss manchmal ziemlich kleine daten von grossen dateien einlesen und der FileStream von Delphi ist manchmal etwas lahm deshalb habe ich versucht es ein wenig zu verbessern

Ich habe es TBufferedFileStream getauft, weil es einfach ein bisschen mehr buffert ohne dass man etwas machen muss. Es ist eigentlich immer schneller, vorallem bei kleineren daten also unter 32 bytes oder so ist es 5.5 mal schneller beim lesen, beim schreiben bis zu 7 mal schneller. Es kann ganz einfach verwendet werden, einfach in deinem Code überall TBufferedFileStream anstatt nur TFileStream schreiben

Delphi-Quellcode:
unit BufferedFileStream;

interface

uses
  Classes;

type
  TBufferedFileStream = class(TFileStream)
  const
    MaxBufSize = 4096;
  private
    FBuffer: array[0..Pred(MaxBufSize)] of Byte;
    FBufOffset: Int64;
    FBufSize: Integer;
    FDirty: Boolean;
  protected
    procedure MoveBuffer(const NewOffset: Int64); virtual;
    procedure FlushBuffer; virtual;
  public
    destructor Destroy; override;
    function Read(var Buffer; Count: Longint): Longint; override;
    function Write(const Buffer; Count: Longint): Longint; override;
  end;

implementation

{ TBufferedFileStream }

destructor TBufferedFileStream.Destroy;
begin
  FlushBuffer;
  inherited;
end;

procedure TBufferedFileStream.MoveBuffer(const NewOffset: Int64);
begin
  FlushBuffer;
  FBufOffset:= NewOffset;
  Seek(FBufOffset, soBeginning);
  FBufSize:= inherited Read(FBuffer, SizeOf(FBuffer));
end;

procedure TBufferedFileStream.FlushBuffer;
begin
  if FDirty then
  begin
    Seek(FBufOffset, soBeginning);
    inherited Write(FBuffer, FBufSize);
    FDirty:= False;
  end;
end;

function TBufferedFileStream.Read(var Buffer; Count: Integer): Longint;
var
  Offset: Int64;
  Delta: Integer;
begin
  if Count < MaxBufSize then
  begin
    Offset:= Seek(0, soCurrent);
    Delta:= Offset - FBufOffset;
    if (Delta < 0) or (Delta + Count > FBufSize) then
    begin
      MoveBuffer(Offset);
      Delta:= Offset - FBufOffset;
    end;
    Result:= FBufSize - Delta;
    if Result > Count then
      Result:= Count;
    if Result > 0 then
    begin
      Move(FBuffer[Delta], Buffer, Result);
    end;
    Seek(Offset + Result, soBeginning);
  end else
    Result:= inherited Read(Buffer, Count);
end;

function TBufferedFileStream.Write(const Buffer; Count: Integer): Longint;
var
  Offset: Int64;
  Delta: Integer;
begin
  if Count < MaxBufSize then
  begin
    Offset:= Seek(0, soCurrent);
    Delta:= Offset - FBufOffset;
    if (Delta < 0) or (Delta + Count > MaxBufSize) then
    begin
      MoveBuffer(Offset);
      Delta:= Offset - FBufOffset;;
    end;
    Result:= Count;
    if FBufSize < Delta + Count then
      FBufSize:= Delta + Count;
    if Result > 0 then
    begin
      Move(Buffer, FBuffer[Offset - FBufOffset], Result);
      FDirty:= True;
    end;
    Seek(Offset + Result, soBeginning);
  end else
    Result:= inherited Write(Buffer, Count);
end;

end.
ich empfehle das allen, die für schnelle Streams aus dateien nicht selber einen Buffer holen möchten

Liebe Grüsse
Laufi
  Mit Zitat antworten Zitat