Einzelnen Beitrag anzeigen

Geri

Registriert seit: 23. Nov 2004
Ort: Feldkirch
47 Beiträge
 
Delphi 2005 Personal
 
#11

Re: ClassType in ein Stream Speichern

  Alt 15. Jan 2008, 16:19
Hallo Hagen

Vien Dank für Deine ausführliche Beschreibung!! Du hast recht, mit den Internals von Klassen habe ich mich noch nicht vertraut gemacht.

Deine Lösung kann ich sehr gut nachvollziehen. Die Geschwindigkeit ist bestimmt deutlich besser als wenn man mit bei jedem Objekt mit Strings operieren muss.

Nachdem du den Lösungsweg so ausführlich bechrieben hast, für andere hier im Forum, welche diesen Weg gehen möchten, "ganz grob " mein Verständnis der Umsetzung:


1.) Schreibe die Objekte mit deren Indizess in ein Stream.
Delphi-Quellcode:

var ClsAry:Array[0..MaxClasses] of TMyClass; // über die Klassen in diesem Array erfolgt der Zugriff beim Lesen
    ClsNameAry:Array[0..MaxClasses] of ShortString; // dieses Array wird an das Ende des Streams geschrieben

// Schreibe die Daten in ein Stream
  Stream:=TStream.Create(.....);
  Stream.Write(AnzElemente,Sizeof(AnzElemente));
  for i:=0 To AnzElemente-1 Do
  Begin
    El:=ElementeList[i];
    ClsIdx:=GetClassIndex(El); // prüfe ob die Klasse in ClsAry bereits vorhanden ist, ansonsten lege den Klassenamen an
                               // hier nicht implementiert
    Stream.Write(ClsIdx,SizeOf(ClsIdx));
  End;
  
  ClsTableOffsett:=stream.Position; // merke den Offsett, an dem die Klassentabelle abgelegt ist
  Stream.Write(MaxClasses,sizeof(MaxClasses)); // schreibe Anzahl der Elemente an Klassennamen
  for i:=0 To MaxClasses-1 Do // schreibe die Klassentabelle
  Begin
    len:=length(ClsNameAry[i];
    Stream.Write(len,sizeof(len));
    Stream.Write(ClsNameAry[i],len);
  End;
  Stream.Write(ClsTableOffsett,sizeof(ClsTableOffsett)); // schreibe den Offsett der Tabelle in den Stream
  

//Restore

// Auslesen der Klassenbeschreiber
  Stream.Position:=Stream.Size-4); // lies Offsett der KlassenNamen aus dem Stream
  Stream.Read(ClassTableLen); // lies Anzahl der Elemente an Klassen
  Stream.Positio:=Stream.Size-ClassTableLen*4-4;
  for i:=0 to ClassTableLen-1 Do // Idendifiziere die Zeiger auf die Klassen
  Begin
    Stream.Read(ClsStrLen,sizeof(ClsStrLen));
    Stream.Read(ClassNameStr,sizeof(ClsStrLen));
    ClsAry[i]:=FindClass(ClassNameStr); // rufe die Hagensche Funktion auf:)
  End;

// Auslesen der Daten
  Stream.Position:=0;
  Stream.Read(AnzElemente,SizeOf(AnzElemente));
  For i:=0 To AnzElemente-1 DO
  Begin
    Stream.Read(ClsIdx,Sizeof(ClsIdx));
      ClsAry[ClsIdx].Load(s); // unter der Voraussetzung, dass die Komponenen von TMyClass über eien Load-Methode verfügen
  End;

Anmerkungen dazu:

1.) Die Klassentabelle könnte man auch bei der Initialisierung des Programmes anlegen (Nachteil, man muss dann u.U. die gesamte Klassentabelle im Stream ablegen.

2.) Man könnte den Index eines Objektes auch in die Klassen verankern und gleich zu beginn setzen. Dann erspart man
sich die Suche in der Tabelle identifizierter Klassen beim Schreiben des Streams, dann aber wieder mit dem Nachteil, dass der Aufand für die Wartung steigt.

3.) Im Code oben habe ich das Klassenarray nicht vom Type TClass verwendet. Ginge auch, auf diese Weise kann man aber unmittelbar auf Methoden zugreifen.

Beste Grüsse

Geri
Gerhard
  Mit Zitat antworten Zitat