AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Von TStringList abgeleitete Klasse inkl. Objecten speichern
Thema durchsuchen
Ansicht
Themen-Optionen

Von TStringList abgeleitete Klasse inkl. Objecten speichern

Ein Thema von Schwedenbitter · begonnen am 8. Jul 2010 · letzter Beitrag vom 9. Jul 2010
Antwort Antwort
Seite 1 von 2  1 2      
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#1

Von TStringList abgeleitete Klasse inkl. Objecten speichern

  Alt 8. Jul 2010, 22:36
Hallo,

Grundproblem:
Ich möchte in meinem Programm viele Daten verwalten. Diese Daten speichere ich nicht in Records, sondern in TmeineDaten = Class(TObject) End; TmeineDaten enthält dann Strings, Integer und alles mögliche andere.
Diese Objecte wiederum verwalte ich alle in einer TStringList; TStringList deshalb, weil die Objecte alle mit Ihrem Namen abgelegt werden und ich dann über Index:=IndexOf('irgendwas') bzw. z.B. (Objects[Index] As TmeineDaten).TollerString:='Hallo'; gut drankomme.
Mir ist SaveToFile() bekannt, was aber die Inhalte meiner Objects nicht mit speichert. TFileStream.WriteComponent() klappt leider auch nicht, weil ich meine Klasse nicht von TComponent abgeleitet habe... Ich möchte gern eine Methode SaveToFile() in meiner Haupt-Klasse (eben abgeleitet von TStringList) implemetieren, die die Object-Daten mit speichert und ohne einen riesigen Aufwand zu machen.
[edit]Ziel ist es später beim Programmstart, die ganzen Daten wieder in die Liste laden zu können[/edit]

Gibt es hierfür eine Lösung/Ideen?

Ich hoffe, mein Problem verständlich rübergebracht zu haben. Falls trotzdem Fragen sind, bitte stellen!

Danke, Alex
Alex Winzer

Geändert von Schwedenbitter ( 8. Jul 2010 um 23:06 Uhr)
  Mit Zitat antworten Zitat
daywalker9

Registriert seit: 1. Jan 2010
Ort: Leer
594 Beiträge
 
Delphi XE3 Professional
 
#2

AW: Von TStringList abgeleitete Klasse inkl. Objecten speichern

  Alt 8. Jul 2010, 22:52
Du könntest eine Klasse von TStringList ableiten mit einem eigenen SaveToFile. Dort machst du für jedes Attribut, das du hast, mit z.b. einem MemoryStream WriteBuffer.

Delphi-Quellcode:
type
  TMeinDaten = class
  property ABC : integer read fAbc write fAbc;
  end;

  //deine savetofile funktion

  ms:=TMemoryStream.create;
  ms.WriteBuffer(meinedaten.abc,sizeof(meinedaten.abc)); //usw, falls mehrere attrbute
  ms.savetofile('MeinDateiname.abc');
  ms.free;
Zum auslesen machst du einfach das gleich wie beim Speichern nur eben ReadBuffer
Lars
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#3

AW: Von TStringList abgeleitete Klasse inkl. Objecten speichern

  Alt 8. Jul 2010, 23:04
Danke für die Antwort!

Die Idee ist gut, aber in meinem Fall nicht praktikabel.
Habe ich doch tatsächlich vergessen zu erwähnen, dass ich das ganze später natürlich wieder laden möchte (geändert, siehe oben). Das Problem ist, dass ich dann jedes Object wieder initialiseren muss etc. pp. Das erzeugt damit einen riesigen overhead.
Im Grunde könnte ich das alles in einer DB in verschiedenen Tabellen speichern. Daran wollte ich mich eigentlich vorbeimogeln. Und ich habe ehrlich gesagt noch nie mit DB in Delphi gearbeitet. Ich habe schon ein wenig mit MySQL experimentiert. Ich wollte aber auch ausdrücklich verhindern, dass ich einen Server aufsetzen muss.

Gruß, Alex
Alex Winzer

Geändert von Schwedenbitter ( 8. Jul 2010 um 23:06 Uhr)
  Mit Zitat antworten Zitat
daywalker9

Registriert seit: 1. Jan 2010
Ort: Leer
594 Beiträge
 
Delphi XE3 Professional
 
#4

AW: Von TStringList abgeleitete Klasse inkl. Objecten speichern

  Alt 8. Jul 2010, 23:13
Nun ja, du könntest den Firebird Embedded Server benutzen. Dann brauchst du nichts installieren, nur die gds32.dll mit ausliefern. Und Komponenten für den Zugriff gibts genug. FIBPlus, Zeos usw...

Und so schwer ist DB auch nicht
Lars
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#5

AW: Von TStringList abgeleitete Klasse inkl. Objecten speichern

  Alt 8. Jul 2010, 23:14
Naja, also deine Objekte sollten schon eine SaveToStream() Methode mitbringen. Dann kannst du in der StringList einfach die SavetoStream() methode überschreiben und jeweils immer die Länge des Namens, den Namen selbst speichern und dann SaveToStream() aufrufen.
Das ist dann zwar ein (unleserliches) Binärformat, und es ist auch ruck-zuck inkompatibel mit Vorgänger/Nachfolgeversionen, aber es geht und nimmt wenig Platz ein

Also TmeineDaten um ein SaveToStream() erweitern (savetofile kannst du der Vollständigkeit halber auch direkt dazutun), und dann sowas machen:
Delphi-Quellcode:
Stream.Write(Items.Count)
for i := 0 to Items.Count - 1 do
begin
  Stream.Write(Items[i].length);
  Stream.Write(Items[i]);
  Stream.Write((Objects[i] as TmeineDaten).SaveToStream(Stream));
end;

Geändert von jfheins ( 8. Jul 2010 um 23:18 Uhr)
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Von TStringList abgeleitete Klasse inkl. Objecten speichern

  Alt 9. Jul 2010, 03:29
TFileStream.WriteComponent() klappt leider auch nicht, weil ich meine Klasse nicht von TComponent abgeleitet habe...
Du musst gar nicht von TComponent ableiten! Es reicht auch, wenn du von TPersistent ableitest. Wenn das auch nicht geht, weil z.B. die Klasse schon einen anderen Vorfahren hat, kannst du immer noch per Compilerschalter die RTTI für deine Klasse aktivieren:
Delphi-Quellcode:
type
{$M+}
TMyClass = class(TObject)
private
  FX: integer;
published
  property X: integer read FX write FX;
  ...
end;
{$M-}
Du musst nur darauf achten, dass alles was gespeichert werden soll im published-Abschnitt steht.
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#7

AW: Von TStringList abgeleitete Klasse inkl. Objecten speichern

  Alt 9. Jul 2010, 08:22
Danke für die Tipps!

So klappt es leider nicht:
Delphi-Quellcode:
   {$M+}
   TDishList= Class(TStringList)                  // Object für Liste der Gerichte
              Private
                  Function GetSystemID(Index: Integer): Integer;
                  Procedure SetSystemID(Index: Integer; Const Value: Integer);
              Public
                  Constructor Create;
                  Destructor Destroy; Override;
                  Function AddDish(Value: TDishes): Integer;
                  Procedure DeleteDish(Index: Integer);
                  Procedure SaveToFile(Const FileName: String); Override;
                  Procedure LoadFromFile(Const FileName: String); Override;
                  Property SystemID[Index: Integer]: Integer
                     Read GetSystemID Write SetSystemID;
              End;
   {$M-}

// Liste in eine Datei speichern
Procedure TDishList.SaveToFile(Const FileName: String);
Var
   I            : Integer;
Begin
   If Count < 1 Then Exit;                        // es muss mind. 1 Eintrag da sein
   With TMemoryStream.Create Do
   Try
      WriteComponent(self);                     // <- inkompatible Typen
      SaveToFile(FileName);                     // alles in der Datei ablegen
   Finally
      Free;
   End;
End;
Wo ist hier mein Denkfehler?

Ich kann leider im Public-Bereich nichts vorweisen. Denn das Object selbst ist ja die Liste. Ich hatte auch versucht, mein Object von TComponent abzuleiten und in Public eine TStringList zu deklarieren. Das geht an sich. Beim Speichern bekomme ich aber auch immer nur eine Datei die 17 Bytes groß ist ...

Gruß, Alex
Alex Winzer
  Mit Zitat antworten Zitat
idefix2

Registriert seit: 17. Mär 2010
Ort: Wien
1.027 Beiträge
 
RAD-Studio 2009 Pro
 
#8

AW: Von TStringList abgeleitete Klasse inkl. Objecten speichern

  Alt 9. Jul 2010, 10:20
Ein inherited in savetofile wäre sicher hilfreich

Wie das derzeit ohne Endlosschleife funktioniert, verteh ich nicht.
Sobald count >0 ist, ruft savetofile sich selbst doch rekursiv auf, ohne Abbruchbedingung für die Rekursion?
Vermutlich löst WriteComponent eine Exception aus, sonst müsste das Programm da abstürzen

edit - Blödsinn, in die with Falle gestolpert - solche Konstruktionen gehören veboten Mit dem with erreicht man in solchen Fällen wirklich nur, dass man den Code endlos studieren muss, um herauszufinden welche Variable da wo gewitht wird.
Aber ohne inherited wird es nicht gehen.

Geändert von idefix2 ( 9. Jul 2010 um 10:29 Uhr)
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#9

AW: Von TStringList abgeleitete Klasse inkl. Objecten speichern

  Alt 9. Jul 2010, 10:43
Aber ohne inherited wird es nicht gehen.
Das glaube ich nicht wirklich.
Denn mein Object erbt die Methode SaveToFile() abgeleitet von TStringList. Das wiederum speichert ja nur die einzelnen Listeneinträge in einer Datei. Ich kann mir daher nicht vorstellen, dass ein inherited irgend etwas bzgl. der mit der Liste gespeicherten Objecte bewirken soll.

Im Moment sieht mein Code - sehr sehr unschön - so aus:
Delphi-Quellcode:
Type
   TDish      = Record                              // Record zum abspeichern
                  SystemID      : Integer;
                  DishName      : String[255];
                  DishType      : Integer;
                  Price         : Currency;
              End;

// Liste in eine Datei speichern
Procedure TDishList.SaveToFile(Const FileName: String);
Var
   I            : Integer;
   Buffer      : TDish;
   OutFile      : File Of TDish;
Begin
   If Count < 1 Then Exit;                        // es muss mind. 1 Eintrag da sein

   AssignFile(OutFile, FileName);               // Dateiname zuweisen
   {$I-}
   FileSetAttr(FileName, $00);                  // alle Attribute löschen
   DeleteFile(PAnsiChar(FileName));               // Datei löschen und
   ReWrite(OutFile);                              // neu anlegen
   For I:=0 To Pred(Count) Do                     // gesamte Liste durchgehen
   Begin
      FillChar(Buffer, SizeOf(Buffer), 0);      // Puffer leeren
      Buffer.SystemID:=(Objects[I] As TDishes).SystemID;
      Buffer.DishName:=(Objects[I] As TDishes).DishName;
      Buffer.DishType:=(Objects[I] As TDishes).DishType;
      Buffer.Price:=    (Objects[I] As TDishes).Price;
      Write(OutFile, Buffer);                     // Daten in Datei ablegen
   End;
   CloseFile(OutFile);                           // die Datei schließen
   {$I+}
End;
Das laden dann analog. Aber das ist umständlich und kompliziert. Und wenn man das später mal warten will, dann muss man statt 5-7 Zeilen für WriteComponent() eben diese vielen behandeln.

Gruß, Alex

P.S. Ich liebe im Übrigen das With! Wenn ich größere Objecte habe, in denen ich - als welchen Gründe auch immer - bestimmte Properties in der Registry oder sonstwie speichern muss, dann spare ich mir etliche Zeilen Code auf diese Art und Weise. Das ist aber nur meine persönliche Meinung.
Alex Winzer
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.861 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Von TStringList abgeleitete Klasse inkl. Objecten speichern

  Alt 9. Jul 2010, 10:47
Gerade bei großen Blöcken kann with aber zu großen Problemen/Seiteneffekten führen
Markus Kinzler
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:02 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