Einzelnen Beitrag anzeigen

Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#1

Records verwalten mit TList und TStream

  Alt 16. Jul 2005, 20:14
Salut.

Ich möchte mir ein Objekt zum Verwalten von Records, deren Quelle ein Stream ist, schaffen.

Im ersten Schritt habe ich mir die Klasse TList genommen und an sie die Information über die Recordgröße geknüpft. Fertig war meine Klasse TRecordList.

Im zweiten Schritt möchte ich erreichen, dass diese Liste ein TStream-Objekt als Standarddatenquelle nutzt. Mit der Eigenschaft Items[Index] soll dann auf jeden Record zugegriffen werden können. Ist der Record noch nicht im Speicher soll er aus dem Stream gelesen und in den Speicher kopiert werden. In jedem Fall gibt Items dann einen Pointer auf den Record im Speicher zurück. (Das vertraute Verhalten von TList.)

Dabei stellt sich mir folgendes Problem: Wie kann ich sicherstellen, dass die Records im Speicher gleich denen im Stream sind? Denn die Anwendung führt an anderer Stelle möglicherweise Schreib-Lese-Operationen an dem Stream durch.

Ich habe mir überlegt, wenn es dasselbe Objekt handhaben würde, bekäme es die Schreib-Lese-Operationen mit, und könnte geschriebene Records aus dem Speicher entfernen. (Besteht noch Lesebedarf werden sie ja erneut in den Speicher geholt.) Folglich brauche ich also ein Objekt, das TStream und TList zugleich ist. Das aber geht in Delphi nicht. Was kann ich tun? Hat jemand eine kozetionell andere Lösung? Ich bin für alles offen.

Noch ein Hinweis: Interfaces kommen nicht in Frage. Im Gesamtkontext gibt es zuviele Delphi-Routinen, die ich benutzen möchte, die TList- und TStream-Objekte erwarten.

Panthrax.

Hier noch etwas Quelltext zum Verständnis:
Delphi-Quellcode:
type
  { TRecordList
  Hier wird nur die Möglichkeit geschaffen, die Information über die Recordgröße bei der Liste zu hinterlegen. }

  TRecordList = class(TList)
    private
    FRecordSize: Integer;

    published
    property RecordSize: Integer read FRecordSize write FRecordSize;

    constructor Create(RecordSize: Integer);
  end;

constructor TRecordList.Create(RecordSize: Integer);
begin
  FRecordSize:=RecordSize;
end;

type
  { TRecordListStreamStreamBounded
  Diese Klasse ist nur eine Beispielimplementierung um zu demonstrieren, was die Eigenschaft Items tun soll, wenn ein Record nachgrfragt wird. }

  TRecordListStreamStreamBounded = class(TRecordList)
    private
    FBoundedStream: TStream;
    function GetItems(Index: Integer):Pointer;
    procedure SetItems(Index: Integer; const Value: Pointer);

    public
    property Items[Index: Integer]:Pointer read GetItems write SetItems; default;

    published
    constructor Create(BoundedStream: TStream);
    { Methoden die Records aus dem Speicher zu entfernen und zu speichern gibt es natürlich auch noch... }
  end;

constructor TRecordListStreamStreamBounded.Create(BoundedStream: TStream);
begin
  FBoundedStream:=BoundedStream;
end;

function TRecordListStreamStreamBounded.GetItems(Index: Integer): Pointer;
var
  RecordPtr: Pointer;
begin
  Result:=inherited Items[Index];
  if Result = NIL then with BoundedStream do
  begin
    GetMem(RecordPtr,RecordSize);
    try
      Seek(soFromBeginning,Index*RecordSize);
      Read(RecordPtr^,RecordSize);
        // Auf Read(...) <> RecordSize zu prüfen spar' ich mir jetzt mal.
    except
      FreeMem(RecordPtr,RecordSize);
    end;
  end;
end;

procedure TRecordListStreamStreamBounded.SetItems(Index: Integer;
  const Value: Pointer);
begin
  inherited Items[Index]:=Value;
end;
  Mit Zitat antworten Zitat