Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Abspeichern von Objekten ?? (https://www.delphipraxis.net/55185-abspeichern-von-objekten.html)

matz 17. Okt 2005 19:16


Abspeichern von Objekten ??
 
Ich beschäftige mich gerade mit dem abspeichern von Daten

die Daten sind in einer StringList als Opjekte gespeichert
Delphi-Quellcode:
  OHeader = class(TObject)
  public
   HDR_TYP       : String[20];
   No            : String;
   Datum         : tDateTime;
   Path          : String;
   Edi           : String;
   PDF           : String;
   Status        : String;
   Nachricht_Typ : String;
   Nachricht_Name : String;
   Bezugsnr      : String;
   Benutzer_ID   : String;
   RegistrierNr  : TStringList;
   RegistrierNr1  : String;
   EdifactNr     : String;
   INH_NR        : String;
  end;
der Versuch die Daten zu speichern und anschließend wieder zu laden sah recht vielversprechend aus
Delphi-Quellcode:

// Daten speichern
if not FileExists(Filename) then TmpStream := TFileStream.Create('C:\test.dat', fmCreate)
    else TmpStream := TFileStream.Create(Filename, fmOpenReadWrite);

Len := SL_Header.Count;
TmpStream.Write(len, SizeOf(len)); // abspeichern wie viele Datensätze

for I := 0 to SL_Header.Count - 1 do
begin
 Header := SL_Header.Objects[i] as oHeader;
 TmpStream.Write(Header, SizeOf(oHeader));
end;

TmpStream.Free;

// gespeicherte Daten gleich wieder einlesen
TmpStream := TFileStream.Create('c:\test.dat', fmOpenRead);

tmpStream.Read(len, SizeOf(len));
sl_Header.Clear;


for I := 0 to len - 1 do Begin
  Header := oHeader.Create;
  header.Path := '';
  tmpStream.Read(Header, SizeOf(oHeader));
  sl_header.AddObject(Header.No,Header);
  end;
tmpstream.free;
leider geht das beim Start des Programmes aber nicht mehr

Delphi-Quellcode:
TmpStream := TFileStream.Create('c:\test.dat', fmOpenRead);
tmpStream.Read(len, SizeOf(len));
for I := 0 to Len-1 do Begin
  Header := oHeader.Create;
  tmpStream.Read(Header, SizeOf(oHeader));
  SL_Header.AddObject(Header.No,Header);
end;
tmpstream.free;
nun meine Frage kann das überhaupt funktionieren ?

schon mal betsen Dank für die Hilfe
gruß Matz

Rastaman 17. Okt 2005 19:20

Re: Abspeichern von Objekten ??
 
Warum nimmst du nicht Records :gruebel:

Kroko1999 17. Okt 2005 19:29

Re: Abspeichern von Objekten ??
 
Der Typ string ist nur ein Pointer,
daher
Delphi-Quellcode:
Stream.Write (Length(MyString),SizeOf(Integer));
Stream.Write (MyString[1],Length(MyString));

jfheins 17. Okt 2005 19:36

Re: Abspeichern von Objekten ??
 
Rastaman war fast richtig, richtig:
Warum nimmst du nicht Records Collections ? :gruebel:

Muetze1 17. Okt 2005 21:31

Re: Abspeichern von Objekten ??
 
Du kannst auch Objekte selber nicht so einfach in den Stream schreiben wie du es machst, weil du damit nur die Adresse des Objektes im Speicher in die Datei ablegst - und diese ist natürlich nicht mehr die gleiche wenn du das Objekt mal wieder lädst. Und vor allem fehlen noch die Daten der Objekte selber...

Taladan 17. Okt 2005 22:02

Re: Abspeichern von Objekten ??
 
Um dir das ganze hin und her mit der Speicherprozedur zu ersparen, ließ dir mal meinen Beitrag zu polimorphen Objekten und deren Speicherung durch. Sollte dir die Arbeit doch ziemlich ersparen.

http://www.delphipraxis.net/internal...ct.php?t=56836

matz 18. Okt 2005 11:05

Re: Abspeichern von Objekten ??
 
Hallo Taladan

ich habe mir die Beiträge
Beitrag 1
und
den von Dir oben genannten mal angesehen und getestet.

In der Version 1 verwendest Du sogar TStrings

leider werden beim Speichern keine Stringwerte gespeichert
** EDIT wenn der Typ in der Routine TBaseObject.SaveToStream(Writer:TWriter) richtig ist wird auch geschrieben **

Somit bleibt nur noch die Stringliste
könntest Du mir noch mal ein wenig behilflich sein

Danke schon mal

viele Grüße Matz

Taladan 18. Okt 2005 23:10

Re: Abspeichern von Objekten ??
 
Nachdem ich mir damals Abend um Abend um die Ohren gehauen hab, um Streams zu speichern über TWriter und TReader was scheinbar nicht möglich ist (zumindest mir nicht möglich war), würde ich deinen TStringList String für String abspeichern lassen.

Das ganze würde ich so angehen (erweiterung zur bekannten Speicherroutine):

Delphi-Quellcode:
      else if typ = 'tStringList' then begin
        s := Tstringlist.Create;
        s := (GetObjectProp(self, PropList^[i].Name) as tStringList);
        Writer.WriteInteger(s.Count);
        for length := 0 to s.Count do
          Writer.WriteString(s[length]);
        s.Free;
      end;
Ich hoffe das bringt dich auf den richtigen Weg, da ich kein Win32 mehr installiert habe, kann ich es nicht ausprobieren. Wenns klappt würde ich mich auf eine Antwort (mit evtl. richtigen ergebnis freuen)

matz 19. Okt 2005 08:52

Re: Abspeichern von Objekten ??
 
nachdem ich mir diverse Beiträge gestern durchgelesen habe, habe ich folgendes probiert

Laden:
Delphi-Quellcode:
     
       else if typ = 'TStringList' then Begin
          dStrings := TStringList.Create;

          MemoryStream := TMemoryStream.Create;
          MemoryStream.Position := 0;
          size := Reader.ReadInteger;
          memorystream.SetSize(size);
          reader.Read(MemoryStream.Memory^, Size);

          MemoryStream.Position := 0;
          dstrings.LoadFromStream(MemoryStream);

          SetObjectProp(self, PropList^[i].Name, dstrings);

          end;
Speichern:

Delphi-Quellcode:
      else if typ = 'TStringList' then Begin
          MemoryStream := TMemoryStream.Create;
          MemoryStream.Position := 0;
          sl_temp.SaveToStream(MemoryStream);
          MemoryStream.Position := 0;
          size := MemoryStream.Size;
          writer.WriteInteger(size);
          MemoryStream.Position := 0;
          Writer.Write(MemoryStream.Memory^, size);
        end;
wobei ich heute Deinen Vorschlag die Stringliste direkt beim speichern als Memorystream zu speichern mal testen werde

Delphi-Quellcode:
s := Tstringlist.Create;
s := (GetObjectProp(self, PropList^[i].Name) as tStringList);
zur Zeit erzeuge ich relativ unelegant und nicht in das Konzept passend direkt in der Routine 'TMyObjectlist.savetostream'
Delphi-Quellcode:
  for i:=0 to c-1 do begin
    // Schreiben des TBaseObjects-Typen-Namen
    WriteClassRef(Writer, Items[i]);
    // Speichern der gewünschten Informationen
    Header := Items[i] as lHeader;
    sl_temp := tStringlist.create;
    sl_Temp := header.RegistrierNr;
    Items[i].SaveToStream(Writer);
    sl_temp.Free;
  end;
den daraus resultierenden Memorystream speichere ich dann in den Hauptstream

des geht zur Zeit sehr gut

Grishnak 19. Okt 2005 10:15

Re: Abspeichern von Objekten ??
 
Ich würde der OHeader-Klasse zwei Methoden zum Speichern bzw. Laden verpassen:

Delphi-Quellcode:
  OHeader = class(TObject)
  public
    { ... }
    procedure WriteToStream(AStream: TStream);
    procedure ReadFromStream(AStream: TStream);
    { ... }
  end;

{ ... }

procedure OHeader.WriteToStream(AStream: TStream);
var
  s: string;
  len: word;
begin
  // HDR_TYP
  AStream.WriteBuffer(HDR_TYP[0], SizeOf(HDR_TYP));
  // No
  len := Length(No);
  AStream.WriteBuffer(len, SizeOf(len));
  AStream.WriteBuffer(No[1], len);
  // Datum
  AStream.WriteBuffer(Datum, SizeOf(Datum));
  // Path
  len := Length(Path);
  AStream.WriteBuffer(len, SizeOf(len));
  AStream.WriteBuffer(Path[1], len);

  { ... }

  // RegistrierNr
  s := RegistrierNr.Text;
  len := Length(s);
  AStream.WriteBuffer(len, SizeOf(len));
  AStream.WriteBuffer(s[1], len);

  { ... }

end;

procedure OHeader.ReadFromStream(AStream: TStream);
var
  s: string;
  len: word;
begin
  // HDR_TYP
  AStream.ReadBuffer(HDR_TYP[0], SizeOf(HDR_TYP));
  // No
  AStream.ReadBuffer(len, SizeOf(len));
  SetLength(No, len);
  AStream.ReadBuffer(No[1], len);
  // Datum
  AStream.ReadBuffer(Datum, SizeOf(Datum));
  // Path
  AStream.ReadBuffer(len, SizeOf(len));
  SetLength(Path, len);
  AStream.ReadBuffer(Path[1], len);

  { ... }

  // RegistrierNr
  AStream.ReadBuffer(len, SizeOf(len));
  SetLength(s, len);
  AStream.ReadBuffer(s[1], len);
  RegistrierNr.Text := s;

  { ... }

end;
Meine Speicher- bzw. Laden-Prozedur kann dann so aussehen (ich würde mir aber eine eigene SL_Header-Klasse implementieren!):

Delphi-Quellcode:
procedure DatenSpeichern(Filename: string);
var
  TmpStream: TFileStream;
  Header: OHeader;
  len, i: integer;
begin
  if not FileExists(Filename)
    then TmpStream := TFileStream.Create('C:\test.dat', fmCreate)
    else TmpStream := TFileStream.Create(Filename, fmOpenWrite);

  len := SL_Header.Count;
  TmpStream.Write(len, SizeOf(len)); // abspeichern wie viele Datensätze

  for i := 0 to SL_Header.Count - 1 do
    begin
      Header := SL_Header.Objects[i] as OHeader;
      Header.WriteToStream(TmpStream);
    end;

  FreeAndNil(TmpStream);
end;

procedure DatenLaden(Filename: string);
var
  TmpStream: TFileStream;
  Header: OHeader;
  len, i: integer;
begin
  if not FileExists(Filename)
    then
      begin
        ShowMessage('Datei "'+Filename+'" nicht gefunden!');
        Exit;
      end;

  TmpStream:=TFileStream.Create(Filename, fmOpenRead);

  TmpStream.ReadBuffer(len, SizeOf(len));
  SL_Header.Clear; // ACHTUNG: bereits eingefügte Objekte werden mMn NICHT (per .Free) freigegeben!

  for i := 0 to len - 1 do
    begin
      Header := OHeader.Create;
      Header.ReadFromStream(TmpStream);
      SL_Header.AddObject(Header.No, Header);
    end;

  FreeAndNil(TmpStream);
end;
Das Ganze ist nicht getestet, aber ich hoffe - sollte es nicht gleich funktionieren - das Prinzip ist verständlich!


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:35 Uhr.
Seite 1 von 2  1 2      

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