Entwickler-Ecke

Dateizugriff - zweidimensionaler dynamischer array speichern?


butterblume - Fr 03.01.03 22:14
Titel: zweidimensionaler dynamischer array speichern?
und genau das in eine INI-Datei speichern.
Geht das überhaupt, wenn ja, wie müßte das aussehen?! :?


Bayo - Sa 04.01.03 17:30

Hi...

Grundsätzlich sind Ini-Files nicht geeignet, um dynamische Datenstrukturen zu speichern... gehen tut es aber natürlich:


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:
var
  FArray: Array of Array of String;
  FSection: String;

procedure InitArray;
var
  i: Integer;
begin
  FSection := 'dynArray';
  SetLength(FArray, 10);
  for i:=0 to Length(FArray)-1 do begin
    SetLength(FArray[i], 2);
    FArray[i, 0] := 'Test'+IntToStr(i);
    FArray[i, 1] := 'Test'+IntToStr(i);
  end;
end;

procedure WriteIni(iniFileName: TFileName);
var
  ini: TIniFile;
  y, x: Integer;
begin
  ini := TIniFile.Create(iniFileName);
  try
    for y:=0 to Length(FArray)-1 do begin
      for x:=0 to Length(FArray[y])-1 do begin
        ini.WriteString(FSection, IntToStr(Y)+';'+IntToStr(x), FArray[y, x]);
      end;
    end;
  finally
    FreeAndNil(ini);
  end;
end;

function GetArrayIndexes(ident: String; var x, y: Integer): Boolean;
var
  p: Integer;
begin
  Result := False;
  p := Pos(';', ident);
  if p > 0 then begin
    try
      y := StrToInt(Copy(ident, 1, p-1));
      x := StrToInt(Copy(ident, p+1, Length(ident)-p))
    except
      Exit;
    end;
    Result := True;
  end;
end;

function ReadIni(iniFileName: TFileName): Boolean;
var
  ini: TIniFile;
  sectionList: TStringList;
  i, x, y: Integer;
begin
  Result := False;
  ini := TIniFile.Create(iniFileName);
  sectionList := TStringList.Create;
  try
    ini.ReadSection(FSection, sectionList);
    SetLength(FArray, 0);
    for i:=0 to sectionList.Count-1 do begin
      if not GetArrayIndexes(sectionList.Strings[i], x, y) then begin
        SetLength(FArray, 0);
        Exit;
      end;
      if y+1 > Length(FArray) then SetLength(FArray, y+1);
      if x+1 > Length(FArray[y]) then SetLength(FArray[y], x+1);
      FArray[y, x] := ini.ReadString(FSection, sectionList.Strings[i], '');
    end;
    Result := True;
  finally
    FreeAndNil(ini);
    FreeAndNil(sectionList);
  end;
end;


Ich habe diesen Code nicht getestet, es könnten evtl. also noch Fehler drin sein! Aber es ist sicherlich ein Ansatz!

Grüsse Dominic


MathiasH - So 05.01.03 10:55

das Prinzip ist ähnlich, aber mit streams(oder TFile) gehts einfacher:
dort muss man an den anfang zei int schreiben die die größe des arrays angeben und dann einfach das gaze array reinspeichern.
Beim laden umgekehrt: erst das array (s.O.) auf die Größe trimmen, die in der Datei steht und dann einfach alles auslesen fertig deutlich weniger Quelltext 8)

PS ich habe mal an einem projekt mitgewirkt und da hatten wir eine ähliche aufgabe. Das Problem wir haben es nie hearausgefunden woran es lag aber mit TFile haben wir das ding nicht zum laufen gebracht(siehe alter Beitrag unter Filezugriff von mir)

MathiasH


butterblume - So 05.01.03 11:52

also bei mir hat es dann doch geklappt, hier der Qellcode, den ich gar nicht für so lang halte :o)

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:
procedure TFrmMain.Save;
var i,n:Integer;
 begin   with TIniFile.Create(savedialog1.filename) do
 try
        if Feldbreite>= FeldHoehe then begin
                For i:=0 to FeldBreite-1 do
                        For n:=0 to FeldHoehe-1 do
                                WriteInteger(IntToStr(i), IntToStr(n), feld[i,n]);
         end
         else begin
                For i:=0 to FeldHoehe-1 do
                        For n:=0 to FeldBreite-1 do
                                WriteInteger(IntToStr(i), IntToStr(n), feld[n,i]);
         end;
        WriteInteger('Infos','Letzter Spieler',spieler);
        WriteInteger('Feld','Feldhöhe',FeldHoehe);
        WriteInteger('Feld','Feldbreite',FeldBreite);
        WriteBool('Infos','Computergegner',Computergegner);
  finally     Free;
  end;
  end;
procedure TFrmMain.Load;
var i,n:Integer;
begin with TIniFile.Create(opendialog1.filename) do
try
        spieler := ReadInteger('Infos', 'Letzter Spieler',spieler);
        FeldHoehe:= ReadInteger('Feld','Feldhöhe',FeldHoehe);
        FeldBreite:= ReadInteger('Feld','Feldbreite',FeldBreite);
        Computergegner:= ReadBool('Infos','Computergegner',Computergegner);
        if FeldBreite>=Feldhoehe then begin //um sicher zu stellen, das wenn Feldbreite kleiner als hoehe ist, Schleife nicht zu früh abbricht
                For i:=0 to FeldBreite-1 do
                        For n:=0 to FeldHoehe-1 do
                                feld[i,n]:= ReadInteger(IntToStr(i),IntToStr(n),Feld[i,n]);
        end
        else begin For i:=0 to Feldhoehe-1 do
                        For n:=0 to Feldbreite-1 do
                                feld[n,i]:= ReadInteger(IntToStr(i),IntToStr(n),Feld[n,i]);
        end;
        StringGrid.RowCount:=FeldHoehe+1;
        StringGrid.ColCount:=FeldBreite;
        Stringgrid.Width:=Stringgrid.ColCount*41+3;
        Stringgrid.Height:=Stringgrid.RowCount*41+3;
        FrmMain.Height:=Stringgrid.Height+40;
        FrmMain.Width:=Stringgrid.Width;
finally     Free;
 end;
 end;

procedure TFrmMain.Speichern1Click(Sender: TObject);
begin
if SaveDialog1.Execute then Save
end;

procedure TFrmMain.Laden1Click(Sender: TObject);
var i,n:Integer;
begin
if OpenDialog1.Execute then Load;

end;