Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record (https://www.delphipraxis.net/167033-speichern-einer-kombination-aus-dynamischen-arrays-statischem-array-und-record.html)

ThorZten 10. Mär 2012 00:35

Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record
 
Guten Morgen!
Ich suche nach einer Lösung, wie ich am Einfachsten die folgende Datenstruktur speichern kann. Darin befinden sich ein dynamisches Array, ein statisches Array und zudem noch ein Record. Gefunden habe ich dazu Lösungen, wie man ein dynamisches und ein statisches Array separat speichert, aber nicht die Kombination aus beiden.

Meine Frage:
Wie kann ich die folgende Struktur in einer Datei speichern und wieder auslesen?
Soll ich lieber komplett auf das statische Array verzichten? Würde es das erleichtern? Ich hatte erst versucht, beide Arrays in zwei verschiedenen Dateien zu speichern, aber schöner wäre es, die Struktur nicht auseinander zu ziehen.

Code:
type
  TGewichte = record
      iDatum : TDateTime;
      iGewicht: double;
    end;

  TPerson = record
    name     : String[10];
    geschlecht: (m,w);
    groesse  : Integer;
    gewichte : array of TGewichte;   // dynamisches Array
  end;

var
  Person: array [1..4] of TPerson;   // statisches Array

Vielen Dank schon einmal für Eure Anregungen!

Beste Grüße,
Thorsten

Medium 10. Mär 2012 00:45

AW: Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record
 
Das schreit mehr nach einer Datenbank (ggf. embedded), oder zumindest XML.

Keldorn 10. Mär 2012 07:12

AW: Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record
 
Hallo,

persönlich würd ich mich für einen Stream und Twriter und Treader entscheiden
so als idee:
Delphi-Quellcode:
Var stream:Tstream;
    writer:Twriter;
    ip,ig:integer;
begin
  Stream:=TFilestream.create(Dateiname,fmcreate);
  try
    writer:=TWriter.Create(stream,4096);
    try
      Writer.WriteInteger(aktuelleVersion);
      //erstmal ne "Version reinschreiben, hier kannst du dann später beim auslesen darauf reagieren
      // (z.B. weil du ab Version5 10 statt 4 Personen hast)
      for ip:=1 to 4  do
        begin
          Writer.WriteStr(Person[ip].name);
          Writer.WriteInteger(Integer(Person[ip].Geschlecht));
          Writer.WriteInteger(Person[ip].groesse);

          //Länge des Arrays reinschreiben
          Writer.WriteInteger(length(Person[ip].gewichte));
          //und nun die einzelnen Gewichte
          for ig:=Low(Person[ip].gewichte) to High(Person[ip].gewichte) do
            begin
              Writer.WriteDate(Person[ip].gewichte[ig].iDatum);
              Writer.WriteDouble(Person[ip].gewichte[ig].iGewicht);
            end;
        end;
    finally
      writer.Free;
    end;
  finally
    Stream.free;
  end;
end;
Das kannst du dir immer noch weiter in einzelne Procs zu besseren Lesbarkeit aufteilen.
Persönlich würde ich aber auch person als dynamisches Array anlegen und statisches und dynamisches nicht mischen.

Auslesen dann genaus andersrum mit Treader und readXYZ.

Gruß Frank

Bummi 10. Mär 2012 07:35

AW: Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record
 
wenn Du Dich für Stream statt Datenbank/XML entscheiden solltest, im obigen Beispiel fehlt noch die Anzahl der Personen.

Keldorn 10. Mär 2012 07:38

AW: Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record
 
Zitat:

Zitat von Bummi (Beitrag 1155752)
wenn Du Dich für Stream statt Datenbank/XML entscheiden solltest, im obigen Beispiel fehlt noch die Anzahl der Personen.

er hats ja statisch deklariert, also
Delphi-Quellcode:
for ip:=1 to 4 do

Bummi 10. Mär 2012 07:39

AW: Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record
 
@Keldorn

sorry, ich war blind:oops:

Keldorn 10. Mär 2012 07:42

AW: Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record
 
macht nix, ich hatte ja schon selber Panik, was ich dem BSP zur frühen Morgenstunde vergessen haben könnte ;-)

himitsu 10. Mär 2012 09:37

AW: Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record
 
Zitat:

Zitat von Bummi (Beitrag 1155752)
wenn Du Dich für Stream statt Datenbank/XML entscheiden solltest, im obigen Beispiel fehlt noch die Anzahl der Personen.

Kommt drauf an, entweder ein eine Längenangabe davor, so wie man es mit der Längenangabe des Delphi-String sieht.
Oder es als Liste markieren/umfassen, mit ListBegin und ListEnd.
Oder einfach nur mit ListEnd das Ende der Liste markieren, so wie man es mit der #0 beim PChar macht.

Bei dem Stream würde ich es also noch mit Blöcken versehn, dann braucht man halt nicht die Anzahl der Personen, da man auf das Ende des Personen-Blocks prüfen kann.

PS: Dann ist es sogar möglich die Datei ohne jegliche Kenntnis des Formats auszulesen, so wie es bei einer XML auch möglich ist.
Wenn man es also ordentlich ausbaut, dann ergibt das quasi eine Art binäre XML-Datei, nur ohne Attribute.

[DELPHI]var stream: TStream;
writer: TWriter;
ip, ig: Integer;
begin
Stream := TFilestream.create(Dateiname,fmcreate);
try
Writer := TWriter.Create(Stream, 4096);
try
Writer.WriteInteger(aktuelleVersion);
for ip := Low(Person) to High(Person) do begin
Writer.WriteString(Person[ip].name);
Writer.WriteInteger(Integer(Person[ip].Geschlecht));
Writer.WriteInteger(Person[ip].groesse);
Writer.WriteListBegin;
for ig := Low(Person[ip].gewichte) to High(Person[ip].gewichte) do begin
Writer.WriteDate(Person[ip].gewichte[ig].iDatum);
Writer.WriteDou

ThorZten 10. Mär 2012 10:37

AW: Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record
 
Guten Morgen noch einmal.

Erst einmal vielen Dank für die zahlreichen Antworten! :-D
Ich muss das Geschriebene jetzt erst einmal verarbeiten. Danke!

himitsu 10. Mär 2012 15:45

AW: Speichern einer Kombination aus dynamischen Arrays, statischem Array und Record
 
Hmm, irgendwie ist da was schiefgegangen. :shock:

So, daß hier hatte ich noch im Zwischenspeicher. (k.A. was ich daran noch geändert hatte)
Delphi-Quellcode:
var stream: TStream;
    writer: TWriter;
    ip, ig: Integer;
begin
  Stream := TFilestream.create(Dateiname,fmcreate);
  try
    Writer := TWriter.Create(Stream, 4096);
    try
      Writer.WriteInteger(aktuelleVersion);
      for ip := Low(Person) to High(Person) do begin
        Writer.WriteString(Person[ip].name);
        Writer.WriteInteger(Integer(Person[ip].Geschlecht));
        Writer.WriteInteger(Person[ip].groesse);
        Writer.WriteListBegin;
        for ig := Low(Person[ip].gewichte) to High(Person[ip].gewichte) do begin
          Writer.WriteDate(Person[ip].gewichte[ig].iDatum);
          Writer.WriteDouble(Person[ip].gewichte[ig].iGewicht);
        end;
        Writer.WriteListEnd;
      end;
    finally
      writer.Free;
    end;
  finally
    Stream.Free;
  end;
end;
Delphi-Quellcode:
        Writer.WriteListBegin;
        for ig := Low(Person[ip].gewichte) to High(Person[ip].gewichte) do begin
          Writer.WriteDate(Person[ip].gewichte[ig].iDatum);
          Writer.WriteDouble(Person[ip].gewichte[ig].iGewicht);
        end;
        Writer.WriteListEnd;

        Reader.ReadListBegin;
        ig := Low(Person[ip].gewichte);
        while Reader.NextValue <> vaNull do begin
          Writer.WriteDate(Person[ip].gewichte[ig].iDatum);
          Writer.WriteDouble(Person[ip].gewichte[ig].iGewicht);
          Inc(ig);
        end;
        Reader.ReadListEnd;
Und letztendlich kann man es auch noch so wie die VCL machen und die Bezeichner gleich mit Dokumentieren.
Delphi-Quellcode:
var stream: TStream;
    writer: TWriter;
    ip, ig: Integer;
begin
  Stream := TFilestream.create(Dateiname,fmcreate);
  try
    Writer := TWriter.Create(Stream, 4096);
    try
      Writer.WriteSignature
      Writer.WriteIdent('FileType');
        Writer.WriteUTF8Str('ThorZten.Personenliste');
      Writer.WriteIdent('Version');
        Writer.WriteInteger(aktuelleVersion);
      Writer.WriteIdent('Personen');
        Writer.WriteListBegin;
          for ip := Low(Person) to High(Person) do begin
            Writer.WriteListBegin;
              Writer.WriteIdent('Name');
                Writer.WriteUTF8Str(Person[ip].name);
              Writer.WriteIdent('Geschlecht');
                Writer.WriteInteger(Ord(Person[ip].geschlecht));
              Writer.WriteIdent('Größe');
                Writer.WriteInteger(Person[ip].groesse);
              Writer.WriteIdent('Gewichte');
                Writer.WriteListBegin;
                  for ig := Low(Person[ip].gewichte) to High(Person[ip].gewichte) do begin
                    Writer.WriteListBegin;
                      Writer.WriteIdent('Datum');
                        Writer.WriteDate(Person[ip].gewichte[ig].iDatum);
                      Writer.WriteIdent('Gewicht');
                        Writer.WriteDouble(Person[ip].gewichte[ig].iGewicht);
                    Writer.WriteListEnd;
                  end;
                Writer.WriteListEnd;
            Writer.WriteListEnd;
          end;
        Writer.WriteListEnd;
    finally
      writer.Free;
    end;
  finally
    Stream.Free;
  end;
end;
Und schon könnte man die Datei auch auslesen, selbst wenn man das Format nicht kennt.
Beim Einlesen kann man quasi Versionsabhänig den richtigen Wert auslesen, da sich über den Ident prüfen läßt, welcher Wert das genau ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:49 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