Autor Beitrag
Moritz M.
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1672



BeitragVerfasst: Di 14.01.03 12:27 
Hi

Ich habe einen record geschrieben, der ca. so aussieht:
ausblenden Quelltext
1:
2:
3:
4:
5:
type Tlalala=record
  anzahl : byte;
  eins   : array[0..300] of string[50];
  zwei    : array[0..300] of string[50];
  drei    : array[0..300] of string[50];


Ich durchlaufe einen TListView so:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
var testvar:Tlalala;
     fs:TFileStream;
...
for i:=0 to ListView1.items.count-1 do
begin
  testvar.eins:=ListView1.items[i].caption;
  testvar.zwei:=ListView.items[i].subitems[0];
  testvar.drei:=ListView.items[i].subitems[2]; 
end;

testvar.anzahl:=ListView1.items.count-1;
...
fs.create(...,fmOpenWrite or fmCreate);
fs.position:=0;
fs.write(testvar,1+((testvar.anzahl+1)*150));
//Das fs.write erklärt sich so:
//1+ zähl für die variable anzahl(Tbyte)
//Dann wird die länge je nach anzahl der einträge gesetzt:
//Ein Eintrag ist 150 Byte groß
//Mal anzahl
fs.free;


Wenn Ich das ganze jetzt mit
ausblenden Quelltext
1:
  fs.read(testvar,anz);					

(anz hab ich davor ausgelesen
fs.read(anzahl{TByte},1);
anz:=1+((anzahl+1)*150));
)
Dann kann ich zwar
testvar.anzahl und testvar.eins in allen möglichen variablen ([1],[2],...) auslesen,
jedoch bleiben testvar.zwei und testvar.drei leer :evil:
Was mach ich falsch?
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Di 14.01.03 12:51 
Und den Quellcode kannst du kompilieren?
Onz hat folgendes geschrieben:
fs.create(...,fmOpenWrite or fmCreate);

Da bekommst du schon mal eine Schutzverletzung. Es muss
fs := TFileStream.Create(...)heißen.


Zitat:
Ich habe einen record geschrieben, der ca. so aussieht

Also wenn ich mir die Zuweisungen der SubItems so anschaue, dann kann der Record auf keinen Fall "ca. so aussehen".


Zitat:
Was mach ich falsch?

Der Record ist linear aufgebaut. D.h. als erstes kommen alle 300 Strings von Eins, dann von Zwei und dann Drei. Dein Speichern-Code ist somit völlig falsch.
Wenn du schon mit "dynamischen" Records arbeiten willst, dann musst du auch jedes Feld extra schreiben und das selbe beim Lesen.

_________________
Ist Zeit wirklich Geld?
Moritz M. Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1672



BeitragVerfasst: Di 14.01.03 12:57 
ausblenden volle Höhe 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:
type Teintrag=record
  anzahl : byte;
  name   : array[0..300] of string[40];
  geb    : array[0..300] of string[10];
  bem    : array[0..300] of string[33];

...
//Export
procedure Tprog.Exportieren_smeClick(Sender: TObject);//Exportieren
var fs:TFileStream;
    lis,lis2:Teintrag;
    i:integer;
begin
  if save.Execute then//Wenn man nicht auf Abbrechen klickt
  begin
    if not(lowercase(copy(save.FileName,integer(length(save.FileName))-3,integer(length(save.FileName))))='.brd') then
      save.FileName:=save.FileName+'.brd';
    fs:=TFileStream.Create(save.FileName,fmOpenWrite or FmCreate);
    if not(fs.size=0) then//Wenn in der Datei was drin is...
    begin
      fs.Free;//...freigeben...
      deleteFile(save.FileName);//...löschen und erstellen :-)...
      fs:=TFileStream.Create(save.FileName,fmOpenWrite or FmCreate);
    end;
    lis.anzahl:=liste.items.count; //Anzahl der Einträge setzen
    for i:=0 to liste.Items.Count-1 do
    begin
      lis.geb[i]:=liste.Items[i].SubItems[0];
      lis.name[i]:=liste.Items[i].Caption;
      lis.bem[i]:=liste.Items[i].SubItems[3];
    end;
    fs.Position:=0;
    fs.Write(lis,1+((liste.items.count+1)*83));
    fs.Free;
    messagedlg('Die Daten wurden erfolgreich exportiert',mtInformation,[mbOk],0);
  end else
  begin
    messagedlg('Das Exportieren wurde abgebrochen',mtInformation,[mbOk],0);
    exit;
  end;
end;
//Import
procedure Tprog.Importieren_smeClick(Sender: TObject);
var fs:TFileStream;
    lis:Teintrag;
    az:byte;
    i,b:integer;
    ini:TiniFile;
    yta,nta,yes,und:boolean;
begin
  if open.Execute then
  begin
    fs:=TFileStream.Create(open.FileName,fmOpenRead or FmShareExclusive);
    fs.Position:=0;
    fs.Read(az,1);
    showmessage(inttostr(az));
    fs.Free;
    fs:=TFileStream.Create(open.FileName,fmOpenRead or FmShareExclusive);
    fs.Position:=0;
    fs.Read(lis,1+((az+1)*83));
    ini:=TiniFile.Create(...);
    yta:=false;
    nta:=false;
    und:=false;
    for i:=0 to lis.anzahl-1 do
    begin
      yes:=false;
      for b:=0 to liste.Items.Count-1 do
      begin
        if liste.Items[b].Caption=lis.name[i] then
        begin
          if not((yta)or(nta)) then
          begin
             case messagedlg('Der Eintrag '+lis.name[i]+' is bereits vorhanden. Überschreiben?',mtWarning,[mbYes,mbNo,mbYesToALl,mbNoToAll],0) of
               mrYes:       yes:=true;
               mrYesToAll:  yta:=true;
               mrNoToAll:   nta:=true;
             end;
             und:=true;
          end;
        end;
      end;
      if (yes)or(yta)or(not(und)) then
      begin
        showmessage(lis.geb[i]);
      {
        ini.WriteString(lis.name[i],'gebtag',lis.geb[i]);
        ini.WriteString(lis.name[i],'bem',lis.bem[i]);}
      end;
    end;
    liste.Clear;
    prog.FormCreate(prog);
    fs.Free;
    ini.Free;
    messagedlg('Die Daten wurden erfolgreich importiert',mtInformation,[mbOk],0);
  end else
  begin
    messagedlg('Das Importieren wurde abgebrochen',mtInformation,[mbOk],0);
    exit;
  end;

So siehst aus.
Und was soll ich machen, dass es geht?
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Di 14.01.03 13:05 
Zuerst solltest du den record packed machen, da anonsten ein Byte auch mal mehr Bytes belegen kann, damit die folgenden Felder auf speziellen Adressen liegen (Alignment).

Eine weitere Verbesserung wäre den Record umzustrukturieren:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
type 
  TEintragItem = packed record
    name: string[40];
    geb: string[10];
    bem: string[33];
   // ...
  end;
  TEintrag=packed record
    anzahl: byte;
    Items: array[0..300] of TEintragItem;
  end;

Jetzt kannst du auch deine Berechnungen durchführen.

_________________
Ist Zeit wirklich Geld?
Moritz M. Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1672



BeitragVerfasst: Di 14.01.03 13:07 
Wie ruf ich dann die vars auf?
testvar:TEintrag

testvar.items.name
??

danke außerdem
Moritz M. Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1672



BeitragVerfasst: Di 14.01.03 13:27 
Juhuu!!!!!!!!!!!!!!!!!
Es geht!!!!!!!!!! :P :P :P
Fett merci!