Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Library: Sonstiges (https://www.delphipraxis.net/45-library-sonstiges/)
-   -   Speichern eines Objektes inkl. aller Felder (https://www.delphipraxis.net/29533-speichern-eines-objektes-inkl-aller-felder.html)

Chewie 10. Sep 2004 14:00


Speichern eines Objektes inkl. aller Felder
 
Angeregt von diesem Thread heute hab ich mal was kleines probiert. Herausgekommen sind zwei einfache Funktionen, mit denen man von jeder beliebigen Klasse alle Felder (also private, protected, public und published) in einer Datei speichern kann. Nichts besonderes, aber man kann doch sehen, dass der Delphi-Compiler auch nur mit Wasser kocht, d.h. Delphi-Objekte sind auch nur Records.

Die beiden Funktionen sind in eine Klasse verpackt, bei der Read-Methode muss das zu übergeben Objekt bereits instanziiert sein. Fehlerabfragen sind nur mangelhaft, ich weiß, aber es ist ja kein Code, der in einem fertigen Programm einsetzbar sein soll, er soll ja nur demonstrativen Zwecken dienen.

Hier ist die Unit:

Delphi-Quellcode:
unit objectwriter;

interface

uses Sysutils, Classes;

type
  TObjectWriter = class(TObject)
  public
    procedure Write(o: TObject; const Filename: String);
    function Read(o: TObject; const Filename: String): Boolean;
  end;


implementation

{ TObjectWriter }

function TObjectWriter.Read(o: TObject; const Filename: String): Boolean;
var
  fs: TFileStream;
  size: Integer;
  p: Pointer;
begin
  Result := False;

  //we fill the already created object "o" with the file data
  if not FileExists(Filename) then
    Exit;
 
  fs := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
  try
    //check if the filesize matches the instance size
    size := o.InstanceSize - 4;
    if size <> fs.Size then
    begin
      fs.Free;
      Exit;
    end;

    //read the file data
    p := Pointer(Integer(o) + 4); //here begins the class fields
    fs.Read(p^, size);
  finally
    fs.Free;
  end;
end;

procedure TObjectWriter.Write(o: TObject; const Filename: String);
var
  fs: TFileStream;
  p: Pointer;
  size: Integer;
begin
  fs := TFileStream.Create(Filename, fmCreate or fmShareExclusive);
  try
    size := o.InstanceSize - 4; //subtract the size of the VMT
    p := Pointer(Integer(o) + 4); //we don't want to save the VMT
    fs.Write(p^, size);
  finally
    fs.Free;
  end;
end;

end.
Der Aufruf erfolgt z.B. so:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  o: TMyClass;
begin
  with TObjectWriter.Create do
  begin
    o := TMyClass.Create;
    o.MyField := 5;
    ShowMessage(InttoStr(o.FMyField));  //should be "5"
    Write(o, 'c:\object.dat');
    o.MyField := 6;
    ShowMessage(InttoStr(o.FMyField));  //should be "6"
    Read(o, 'c:\object.dat');
    ShowMessage(InttoStr(o.FMyField));  //should be "5" again
    o.Free;
    Free;
  end;
end;
Infos über den Aufbau von Objekten gibt es z.B. hier.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:50 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz