Autor Beitrag
habnefrage
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mi 17.07.02 20:53 
Hi,

ich habe ein Objekt "erschaffen" und erstelle davon zur Laufzeit mehrere Instanzen mit natürlich immer wieder anderen Eigenschaften. (Dazu sind die Dinger ja verdammt nochmal auch da :) )

Nun möchte ich, dass die eingestellten Eigenschaften beim nächsten Programmstart noch verfügbar sind. Was liegt da also näher, als die komplette INstanz in eine Datei zu schreiben.
Beim nächsten Programmstart will ich die Datei wieder auslesen und die Instanzen sollen bitte schön alle wieder verfügbar sein.


Geht das wohl irgendwie???
Wenn JA, kann mir jemand ein paar Grundgedanken geben, wie ich das problem angehe??? (Ich habe noch nie etwas mit Dateizugriffen zu tun gehabt... höchstens mal mit ner INI-Datei)
Pit
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 160



BeitragVerfasst: Mi 17.07.02 22:19 


Zuletzt bearbeitet von Pit am Sa 05.10.02 07:57, insgesamt 1-mal bearbeitet
Pit
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 160



BeitragVerfasst: Do 18.07.02 02:34 


Zuletzt bearbeitet von Pit am Sa 05.10.02 07:57, insgesamt 1-mal bearbeitet
habnefrage Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Do 18.07.02 08:55 
Titel: Vielen Dank
Hi Pit,

ich danke für die Antwort...
Ich denke, ich werde einfach die Daten in einem Record speichern und dies dann in solch eine Typisierte Datei schreiben... das sollte das Einfachste sein.

mfg

Christian Tasche
Pit
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 160



BeitragVerfasst: Do 18.07.02 14:56 
Titel: Re: Vielen Dank


Zuletzt bearbeitet von Pit am Sa 05.10.02 07:58, insgesamt 1-mal bearbeitet
Eisenherz
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 48



BeitragVerfasst: Do 18.07.02 22:36 
Hi habnefrage,

ich kann Pit nur zustimmen. Zusätzlich solltest Du etwas in die Zukunft blicken. Mit neuen Versionen Deines Programmes bekommen Deine Objekte wahrscheinlich weitere Eigenschaften, die Du natürlich auch abspeichern werden willst. Dann wirst Du Dein Dateiformat ändern müssen. Natürlich willst Du die alten Dateien nicht wegschmeißen müssen, sondern willst dass Deine neue Programmversion auch die alten Dateien einlesen kann. Mit typisierten Dateien wirst Du dann für jedes Format einen eigenen Code haben.
Ich habe Pits Beispiel hergenommen und so abgeändert, dass es total einfach ist den Schülern weitere Attribute zu verpassen. Ich setze dazu allerdings nicht direkt auf den Streamklassen der VCL auf, sondern auf eigenen Klassen, die aber jeder kostenlos von meiner Homepage herunter laden kann.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
unit Mainform;  

interface

uses
  RakBinaryStreamData,
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, contnrs;

type
  TSchuelerList = class;

  TForm1 = class(TForm)
    BtnSave: TButton;
    BtnLoad: TButton;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure BtnSaveClick(Sender: TObject);
    procedure BtnLoadClick(Sender: TObject);
  private
    { Private-Deklarationen }
    FSchuelerliste: TSchuelerList;
  public
    { Public-Deklarationen }
  end;

 TSchueler = class(TObject)
 private
  FName: String;
  FVorname: String;
  FStufe: Integer;
 public
  procedure LoadFromBinaryTag(const Tag: TRakBinaryTag);
  procedure SaveToBinaryTag(const Tag: TRakBinaryTag);

  property Name: String read FName write FName;
  property Vorname: String read FVorname write FVorname;
  property Stufe: Integer read FStufe write FStufe;
 end;

 TSchuelerList = class(TObject)
 private
  FList: TObjectList;
  function GetCount: Integer;
  function GetSchueler(Index: Integer): TSchueler;
 public
  constructor Create;
  destructor Destroy; override;
  function AddSchueler: TSchueler;
  procedure Clear;
  procedure LoadFromBinaryTag(const Tag: TRakBinaryTag);
  procedure SaveToBinaryTag(const Tag: TRakBinaryTag);
  procedure LoadFromFile(const Filename: String);
  procedure SaveToFile(const Filename: String);
  property Count: Integer read GetCount;
  property Schueler[Index: Integer]: TSchueler read GetSchueler; default;
 end;

var
  Form1: TForm1;

implementation

{$R *.DFM}


{ TSchueler }

procedure TSchueler.LoadFromBinaryTag(const Tag: TRakBinaryTag);
begin
  FName := Tag.AttributeAsString('Name''');
  FVorname := Tag.AttributeAsString('Vorname''');
  FStufe := Tag.AttributeAsInteger('Stufe'1);
end;

procedure TSchueler.SaveToBinaryTag(const Tag: TRakBinaryTag);
begin
  TRakBinaryAnsiString.AddToTag(Tag, 'Name', FName);
  TRakBinaryAnsiString.AddToTag(Tag, 'Vorname', FVorname);
  TRakBinaryWord.AddToTag(Tag, 'Stufe', FStufe);
end;

{ TSchuelerList }

function TSchuelerList.AddSchueler: TSchueler;
begin
  Result := TSchueler.Create;
  FList.Add(Result);
end;

procedure TSchuelerList.Clear;
begin
  FList.Clear;
end;

constructor TSchuelerList.Create;
begin
  FList := TObjectList.Create;
end;

destructor TSchuelerList.Destroy;
begin
  FList.Free;

  inherited;
end;

function TSchuelerList.GetCount: Integer;
begin
  Result := FList.Count;
end;

function TSchuelerList.GetSchueler(Index: Integer): TSchueler;
begin
  Result := TSchueler(FList[Index]);
end;

procedure TSchuelerList.LoadFromBinaryTag(const Tag: TRakBinaryTag);
var
  TagList: IRakBinaryTagList;
  I: integer;
begin
  Clear;
  TagList := Tag.FindTagsByName('Schueler');
  for I := 0 to TagList.Count - 1 do
    AddSchueler.LoadFromBinaryTag(TagList.Items(I));
end;

procedure TSchuelerList.LoadFromFile(const Filename: String);
var
  Data: TRakBinaryStreamData;
begin
  Data := TRakBinaryStreamData.Create;
  try
    if (Data.LoadFromFile(Filename) <> blrOK)
        or (Data.ApplicationName <> 'Schuelerliste'then
    begin
      ShowMessage('Unbekanntes Dateiformat');
    end
    else
    begin
      LoadFromBinaryTag(Data);
    end;
  finally
    Data.Free;
  end;
end;

procedure TSchuelerList.SaveToBinaryTag(const Tag: TRakBinaryTag);
var
  I: integer;
begin
  for I := 0 to Count - 1 do
    Schueler[I].SaveToBinaryTag(Tag.AddTag('Schueler'));
end;

procedure TSchuelerList.SaveToFile(const Filename: String);
var
  Data: TRakBinaryStreamData;
begin
  Data := TRakBinaryStreamData.Create;
  try
    Data.ApplicationName := 'Schuelerliste';
    SaveToBinaryTag(Data);
    Data.SaveToFile(Filename);
  finally
    Data.Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Item: TSchueler;
begin
  FSchuelerliste := TSchuelerList.Create;

  Item := FSchuelerliste.AddSchueler;
  Item.Name := 'Müller';
  Item.Vorname := 'Lischen';
  Item.Stufe := 4;

  Item := FSchuelerliste.AddSchueler;
  Item.Name := 'Rudi';
  Item.Vorname := 'Unser';
  Item.Stufe := 5;

  Item := FSchuelerliste.AddSchueler;
  Item.Name := 'Musterman';
  Item.Vorname := 'Max';
  Item.Stufe := 1;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FSchuelerliste.Free;
end;

procedure TForm1.BtnSaveClick(Sender: TObject);
begin
  if SaveDialog1.Execute then
    FSchuelerliste.SaveToFile(SaveDialog1.FileName);
end;

procedure TForm1.BtnLoadClick(Sender: TObject);
begin
  if OpenDialog1.Execute then
    FSchuelerliste.LoadFromFile(OpenDialog1.FileName);
end;

end.


Dadurch, dass jede Information zusammen mit einem Namen abgespeichert wird, ist es kein Problem bei evtl. nicht vorhandene Informationen einen Defaultwert zu setzen.

Das hat allerdings auch Nachteile. Die so erzeugten Dateien sind viel größer, als die, welche durch Pits Code erzeugt werden.
Weiterhin müssen alle Daten erst im Hauptspeicher zwischengepuffert werden, bevor sie auf die Platte geschrieben werden. Für extrem große Datenmengen ist das also nicht so geeignet.

Lass Dich nicht durch den Unfang des Codes abschrecken. Die Codestücke auf die es ankommt sind folgende:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
procedure TSchuelerList.SaveToFile(const Filename: String);
var
  Data: TRakBinaryStreamData;
begin
  // Den Container erzeugen, in den wir alle abzuspeichernden Daten reinstecken
  Data := TRakBinaryStreamData.Create;
  try
    // Damit wir unsere Daten beim Laden als unsere erkennen können
    Data.ApplicationName := 'Schuelerliste';
    // Die zu speichernden Daten in den Zwischencontainer stecken
    SaveToBinaryTag(Data);
    // Den Zwischencontainer mit allen Daten in die Datei speichern
    Data.SaveToFile(Filename);
  finally
    Data.Free;
  end;
end;

procedure TSchuelerList.SaveToBinaryTag(const Tag: TRakBinaryTag);
var
  I: integer;
begin
  // Jeder Schüler bekommt seinen eigenen Unterknoten, in dem er seine Attribute ablegen kann
  for I := 0 to Count - 1 do
    Schueler[I].SaveToBinaryTag(Tag.AddTag('Schueler'));
end;

procedure TSchueler.SaveToBinaryTag(const Tag: TRakBinaryTag);
begin
  // Die drei Attribute in den Zwischencontainer stecken
  TRakBinaryAnsiString.AddToTag(Tag, 'Name', FName);
  TRakBinaryAnsiString.AddToTag(Tag, 'Vorname', FVorname);
  TRakBinaryWord.AddToTag(Tag, 'Stufe', FStufe);
end;

procedure TSchuelerList.LoadFromFile(const Filename: String);
var
  Data: TRakBinaryStreamData;
begin
  // Den Zwischencontainer erzeugen
  Data := TRakBinaryStreamData.Create;
  try
    // Die Daten des Zwischencontainer aus der Datei laden
    if (Data.LoadFromFile(Filename) <> blrOK)
        or (Data.ApplicationName <> 'Schuelerliste'then
    begin // Wenn das Laden nicht geklappt hat oder es nicht unsere Daten sind
      ShowMessage('Unbekanntes Dateiformat');
    end
    else
    begin
      // Die Schülerliste anahnd der Daten im Zwischencontainer rekonstruieren
      LoadFromBinaryTag(Data);
    end;
  finally
    Data.Free;
  end;
end;

procedure TSchuelerList.LoadFromBinaryTag(const Tag: TRakBinaryTag);
var
  TagList: IRakBinaryTagList;
  I: integer;
begin
  // Evtl alte Schüler löschen
  Clear;
  // Die Unterknoten anfordern, welche die Daten der Schüler enthalten
  TagList := Tag.FindTagsByName('Schueler');
  // Für jeden Knoten wird ein Schüler erzeugt, der seine Daten selbst aus dem Knoten liest
  for I := 0 to TagList.Count - 1 do
    AddSchueler.LoadFromBinaryTag(TagList.Items(I));
end;

procedure TSchueler.LoadFromBinaryTag(const Tag: TRakBinaryTag);
begin
  // Die Werte der drei Attribute aus dem Knoten lesen.
  // Wenn die Daten zu einem Attribut nicht zur Verfügung stehen, dann wird ein Defaultwert genommen
  FName := Tag.AttributeAsString('Name''');
  FVorname := Tag.AttributeAsString('Vorname''');
  FStufe := Tag.AttributeAsInteger('Stufe'1);
end;


Moderiert von user profile iconraziel: Code- durch Delphi-Tags ersetzt

_________________
aloa Eisenherz
habnefrage Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Fr 19.07.02 08:59 
Titel: Das problem ist...
...dass ich das Programm als Abschlussarbeit für nen Kumpel schreibe. Dass da mal neue Versionen, oder evtl Änderungen der Eigenschaften kommen, klingt gar nicht so unlogisch, aaaaaber wenn ich da mit einer fremden Klasse ankomme, dann wird mein Kumpel es erstens nicht verstehen und der profressor ganz schön mistrauisch werden :)

Aber ich schaue es mir mal in Ruhe an. Kennt ihr vielleicht ein paar coole Tutourials zum Thema Streams?
Eisenherz
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 48



BeitragVerfasst: Fr 19.07.02 15:01 
Ich kenne nur das Tutorial, das ich selbst verbrochen habe. :D

_________________
aloa Eisenherz