Autor Beitrag
wafrie
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19


Delphi 2005 Personal
BeitragVerfasst: So 01.10.06 20:40 
Hallo zusammen,

ich habe in einem Programm einen eigenen, sehr umfangreichen record spezifiziert. In diesem record sind zahlreiche Arrays definiert. Anfangs habe ich dabei noch statische Arrays verwendet, nun aber das komplette Programm auf dynamische umgestellt. Leider habe ich erst jetzt festgestellt, dass beim Speichern in Filestreams gerade statische Arrays von Vorteil sind. Dennoch sind die dynamischen Arrays doch eigentlich für den Programmablauf selbst die elegantere und vor allem flexiblere Lösung. Um jetzt in einen Filestream zu speichern, müsste ich nun eigentlich die Länge jedes einzelnen Arrays auslesen und mit im abspeichern. Das Problem ist jedoch, dass viele Arrays ineinander verschachtelt sind (In einem record habe ich einen anderen record als dynamischen array definiert. Doch in diesem ist wiederum ein anderer record als dynamischer array spezifiziert.) Gibt es eine Möglichkeit, den dynamischen Array dennoch ohne großen Aufwand, vielleicht auch ohne Filestream, abzuspeichern? Oder ist es doch besser, wenn ich in diesem Fall statische Arrays verwende?

Vielen Dank für eure Hilfe!
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2145

WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
BeitragVerfasst: So 01.10.06 20:45 
Könntest du bitte mal einen Beispielcode zeigen, wie jetzt deine Records und Arrays deklareirt sind? Ich glaube dann wirds viel verständlicher.

Du könntest evtl. am Anfang des Streams erstmal Speichern, wie viele Elemente dein Array hat und demnach auslesen.
Je nach verwendetem Zahlentyp hast du ja eh eine feste Länge.

Gruß alias5000

_________________
Programmers never die, they just GOSUB without RETURN
wafrie Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19


Delphi 2005 Personal
BeitragVerfasst: So 01.10.06 21:02 
Hallo,

leider steht mir der konkrete Programmtext momentan nicht zur Verfügung. Allgemein bezieht sich meine Frage auf eine derartige Datenstruktur:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
type
  Datentyp1=record
  V1: array of integer;
  V: string;
end;

type
  Datentyp2=record
  Daten: array of Datentyp1;
end;

var variable: Datentyp2;


Hier sind also Arrays ineinander verschachtelt. Ich hoffe, dass dir dieses Beispiel weiterhilft.
Kroko
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1284

W98 W2k WXP
Turbo D
BeitragVerfasst: Mo 02.10.06 10:08 
(a) mal komplett als eine Klasse
(b) SaveTofile als Denkansatz "Load" entsprechend
(c) ungetestet
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:
unit Unit1;

interface

uses
  Classes;
  
type

TMyRecord = record
    V1: array of integer;
    V: string;
  end;
TMyArray = array of TMyRecord;

{-- Class: --}
TMyClass = class
    constructor Create;
    destructor Destroy; override;
  private
    FData: TMyArray;
  protected
  public
    procedure SaveToFile (const AFileName: String);
end;

implementation

constructor TMyClass.Create;
begin
  inherited Create;
end;

destructor TMyClass.Destroy;
begin
  Finalize (FData);
  inherited Destroy;
end;

procedure TMyClass.SaveToFile (const AFileName: String);
var
  F: TFileStream;
  I,C1: Integer;
  J,C2: Integer;
begin
  F := TFileStream.Create(AFileName,fmCreate);
  C1 := Length (FData);
  F.Write(C1,SizeOf(C1));
  if C1>0 then
    for I := 0 to C1-1 do
    begin
      C2 := Length (FData[I].V1);
      F.Write (C2,SizeOf(C2));
      if C2>0 then
        for J := 0 to C2-1 do
          F.Write(FData[I].V1[J],SizeOf (Integer));
        { oder }
        // F.Write (FData[I].V1[0],C2*SizeOf(Integer));
      C2 := Length (FData[I].V);
      F.Write (C2,SizeOf(C2));
      if C2>0 then
        F.Write (FData[I].V[1],C2);
    end;

  F.Free;
end;

end.

_________________
Die F1-Taste steht nicht unter Naturschutz und darf somit regelmäßig und oft benutzt werden! oder Wer lesen kann, ist klar im Vorteil!


Zuletzt bearbeitet von Kroko am Mo 02.10.06 10:53, insgesamt 1-mal bearbeitet
Jack Falworth
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 222

Win XP Pro, Slackware 10.0
D5 Enterprise, C++, ABAP
BeitragVerfasst: Mo 02.10.06 10:21 
gibt es nicht eine Funktion (vielleicht auch eine überladene sizeof-Funktion) für Records?
dann ermittelst du einfach die Größe des Records und gut ist.

Bin momentan nicht zu Hause und hab daher auch nicht meine Delphi-Wälzer zur Hand, aber vielleicht weiß das hier zufällig gerade jemand.

_________________
Andere zu kritisieren ist mitunter eine Möglichkeit, sich selbst ins bessere Licht zu setzen.
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mo 02.10.06 10:45 
Mit Sizeof kommt man hier nicht weiter, weil dynamische Arrays ja eben dynamisch, also auf dem Heap angelegt werden. Im Record ist dann nur ein Zeiger auf das Array gespeichert, das Array-Feld im Record hat somit eine feste Grösse von 4 Bytes. Daher kann man den Record auch nicht mehr einfach so in den Stream schreiben - da landet dann nicht mehr das Array drin, sondern nur der Zeiger, was natürlich komplett wertlos ist.
Arbeit bedeutet das Ganze also in jedem Fall. Ich würde es wahrschienlich so machen, dass ich die Arrays als letzte Felder des Records definiere, so dass jeder Record aus einem Abschnitt mit fester Grösse und einem mit variabler Grösse besteht.
Je nach Umfang des Programms mag es sinnvoll sein, anstelle von Records und Arrays Objekte und Listen zu verwenden. Alle Klassen aus denen dein Datenmodell dann besteht, kriegen eine Serialiserungs- und eine Deserialisierungsmethode, die das Objekt in einen Stream schreibt bzw. daraus liest.
Du könntest auch statt eines Streams XML als Datenformat benutzen - entweder in Kombination mit dem objektorierten Ansatz oder weiter auf Records basierend. Dann brauchst du dir keine Gedanken um Array-Längen und dergleichen machen und die Fehlersuche ist einfacher, weil du die erzeugten Dateien einfach ansehen kannst. Der Nachteil von XML ist natürlich, dass die erzeugten Dateien grösser werden und langsamer gelesen und geschrieben werden.

Stefan

_________________
Ein Computer ohne Windows ist wie eine Schokoladentorte ohne Senf.
wafrie Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19


Delphi 2005 Personal
BeitragVerfasst: Mo 02.10.06 15:06 
Hallo,

leider habe ich noch nie mit XML gearbeitet. Deshalb erscheint mir dieser Ansatz für diesen Zweck zu kompliziert. Zudem bin ich noch Anfänger. Gibt es keine Möglichkeit, die Größe eines dynamischen Arrays zu bestimmen? Denn SizeOf funktioniert in diesem Fall ja nicht.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 02.10.06 15:16 
Moin!

High(Array)*SizeOf(Element), würde ich sagen. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Kroko
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1284

W98 W2k WXP
Turbo D
BeitragVerfasst: Mo 02.10.06 15:24 
user profile iconNarses hat folgendes geschrieben:
Moin!

High(Array)*SizeOf(Element), würde ich sagen. ;)

cu
Narses


muss es nicht Length(Array)*SizeOf(Element) heißen :wink:

siehe hier
user profile iconKroko hat folgendes geschrieben:
...
ausblenden Delphi-Quelltext
1:
        // F.Write (FData[I].V1[0],C2*SizeOf(Integer));					
...

_________________
Die F1-Taste steht nicht unter Naturschutz und darf somit regelmäßig und oft benutzt werden! oder Wer lesen kann, ist klar im Vorteil!
wafrie Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19


Delphi 2005 Personal
BeitragVerfasst: Mo 02.10.06 15:29 
Hallo,

danke für euere unermüdliche Hilfe. Beim Ausprobieren habe ich auch festegestellt, dass man length statt high braucht. Ich denke, dass es mir mit euren vielen Vorschlägen nun endlich gelingt, den Array abzuspeichern!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 02.10.06 15:33 
Moin!

Oh, stimmt, fehlt ein +1, also korrekt:

(High(Array)+1)*SizeOf(Element) <=> Length(Array)*SizeOf(Element)

;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.