Entwickler-Ecke

Dateizugriff - Ein Record aus typisierte Datei füllen.


sunday_2 - Do 21.11.02 17:01
Titel: Ein Record aus typisierte Datei füllen.
Hi Leute,

ich hab ein riesen Prob: Ich habe in meinem Programm bisher mit Paradox 7 Tabellen gearbeitet und alles lief wunderbar. Nun sagt Chef alle Paradox 7 Tabellen raus und in typisierte Datei schreiben. :evil:
Nun gut, reinschreiben habe ich hinbekommen (denk ich).


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:
procedure TSpieldefinition.b_sound_vorClick(Sender: TObject);
var i,j: integer;
    TextDatei:TextFile;
begin
        if SaveDialog1.Execute then
        begin
           AssignFile(TextDatei,SaveDialog1.Filename);
           Rewrite(TextDatei); //Datei erstellen
       for i:=1 to 26 do
        begin
           Write(TextDatei,AEvent[i].Name);
           Write(TextDatei,AEvent[i].Zahl);
           Write(TextDatei,AEvent[i].Text);
           Write(TextDatei,AEvent[i].Grafik);
           Write(TextDatei,AEvent[i].Sound);
        end;
        for i:= 1 to 23 do
        for j:= 1 to 9 do
        begin
           Write(TextDatei,tormatrix[i,j].Name);
           Write(TextDatei,tormatrix[i,j].color);
        end;
        end;
end;

Nun will ich die Datei wieder einlesen und die Arrays (AEvent und tormatrix) wieder füllen. Habe dazu folgenden Coden bisher:

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:
procedure TSpieldefinition.b_datei_oeffnen_oeffnenClick(Sender: TObject);
var
    i,j: integer;
    Einlesen:Textfile;
begin
        if opendialog2.Execute then
           begin
              AssignFile(Einlesen, OpenDialog2.Filename);
              Reset(Einlesen);
              for i:=1 to 26 do
              begin
                 Read(Einlesen,AEvent[i].Name);
                 Read(Einlesen,AEvent[i].Zahl);
                 Read(Einlesen,AEvent[i].Text);
                 Read(Einlesen,AEvent[i].Grafik);
                 Read(Einlesen,AEvent[i].Sound);
              end;
              for i:=1 to 23 do
              for j:= 1 to 9 do
              begin
                 Read(Einlesen,tormatrix[i,j].Name);
                 Read(Einlesen,tormatrix[i,j].Color);
              end;
              button1.Click;
end;

Schmiert aber jedesmal ab, wenn ich die Datei öffnen will.
:?
Hat jemand eine :idea:


Keldorn - Do 21.11.02 17:14

hallo,

auf den ersten Blick:
1. closefile fehlt. damit ist die Dat noch offen und du hast keinen zugriff mehr
2. so wird das gar nix , schau dir mal eine von dir erzeugte Datei an:
wenn du eine Textdatei hast schreibst du
z.B. name rein (bsp: "Synday") bei auslesen liest du mit read aus, woher aber soll read wissen, wie lang das einzulesende sein soll?

nimm mal readln statt read und writeln statt write.
aber so wie du deinen Code aufgebuat hast, bekommst du probleme, wenn sich an der reihenfolge was ändert.

Frank


Keldorn - Do 21.11.02 17:26

lies dir das mal durch:

http://www.tutorials.delphi-source.de/sequdateien/index.shtml

du kannst meines Wissens nach aber nicht 2 unterschiedliche Records in einer typisierten Datei unterbringen

Frank


Klabautermann - Do 21.11.02 17:27
Titel: Re: Ein Record aus typisierte Datei füllen.
Hallo,
sunday_2 hat folgendes geschrieben:
ich hab ein riesen Prob: Ich habe in meinem Programm bisher mit Paradox 7 Tabellen gearbeitet und alles lief wunderbar. Nun sagt Chef alle Paradox 7 Tabellen raus und in typisierte Datei schreiben. :evil:


Schlechte Idee wenn du micht fragst. Ich bin zwar abdolut kein Paradox Fan aber Datenbanken sind doch wesentlich leistungsstärker als ein einfaches Typ-File System.

sunday_2 hat folgendes geschrieben:
Nun will ich die Datei wieder einlesen und die Arrays (AEvent und tormatrix) wieder füllen.


Du kannst die hier [http://downloads.oitmann.de/samples/TypFileDemo.zip] ein Beispiel runterladen, vieleicht hilft es dir.

Gruß
Klabautermann


Klabautermann - Do 21.11.02 17:29

Hallo,
Keldorn hat folgendes geschrieben:
nimm mal readln statt read und writeln statt write.

bei Typisierten Dateien sollte er tatsächlich Read und Write verwenden. Bei TextDateien ReadLn und WriteLn.

Gruß
Klabautermann


Klabautermann - Do 21.11.02 17:34

Hallo,
Keldorn hat folgendes geschrieben:
du kannst meines Wissens nach aber nicht 2 unterschiedliche Records in einer typisierten Datei unterbringen

Er könnt diese zu einem Varianten Record-Typen zusammenfassen. Davon würde ich aber abraten, da er damit recht viel verschitt hat und somit Plattenplatz verschwendet.

Gruß
Klabautermann


Keldorn - Do 21.11.02 17:36

Klabautermann hat folgendes geschrieben:
Hallo,

bei Typisierten Dateien sollte er tatsächlich Read und Write verwenden. Bei TextDateien ReadLn und WriteLn.



das ist klar, aber er hat ja beides in seinen Code gemuddelt:

Zitat:

var
i,j: integer;
Einlesen:Textfile;


wulfskin - Do 21.11.02 18:00

Keldorn hat folgendes geschrieben:

du kannst meines Wissens nach aber nicht 2 unterschiedliche Records in einer typisierten Datei unterbringen
Warum sollte das nicht gehen? Wenn man weiss wie die Records aussehen, dann ist das absolut kein Problem. Ich programmieren seit je her mit Dateien, da ich kein Delphi Professional habe und deshalb leider nicht mit einer Datenbank arbeiten kann und bis jetzt habe ich alles noch in einer Datei speichern können! Warum auch nicht? Also wenn du, sunday_2, weiterhin Probleme damit hast, schreib ich dir auch ein Beispiel. Aber um ein paar Stichworte zu nennen:
"Old" Pascal:
File, BlockRead, BlockWrite (ich nehm die immer noch)
Delphi:
TFileStream

Gruß wulfskin!


Klabautermann - Do 21.11.02 18:06

Hallo,
wulfskin hat folgendes geschrieben:
Keldorn hat folgendes geschrieben:

du kannst meines Wissens nach aber nicht 2 unterschiedliche Records in einer typisierten Datei unterbringen
Warum sollte das nicht gehen?

die Betonung lag auf Typisierte-Dateien. Was du verwendest sind Untypisierte-Dateien. Damit geht natürlich alles.

Gruß
Klabautermann


wulfskin - Do 21.11.02 18:13

Klabautermann hat folgendes geschrieben:
Hallo,
die Betonung lag auf Typisierte-Dateien. Was du verwendest sind Untypisierte-Dateien. Damit geht natürlich alles.

Gruß
Klabautermann
Ihr habt recht! Sorry! Also lieber untypisierte Dateien nehmen ;-)!

Gruß wulfskin!


Keldorn - Do 21.11.02 18:14

@wulfskin; bisher war ich der ansicht, wenn du Fileof Record Typx verwendest, da nur auch records Typx lesen schreiben kannst. Synday hat aber 2 unterschiedliche Records.
Rein vom ansatz her, woher willst du wissen, wieviele Datensätze von einem Typ in der datei drin sind. Da müßte man ja nochmal 2 zusätzliche variablen mit abspeichern, wo erstmal die anzahl mit drin steht ... und das wird so oder so doch mit einem File of Record ... nicht gehen.

Beispiel brauch ich keines, da ich meine Daten anders schreibe
(rewrite/reset ..., 1 Datensatz pro Zeile mit einem Trennzeichen (z.B. Tab),damit kann ich Änderungen in den Records besser behandeln)

Frank

edit : aarggh, zu langsam und zu viel getippert :wink:


sunday_2 - Fr 22.11.02 10:21

OK, OK!

Erstmal danke für soviel hilfe. Das Tutoral ist übrigens echt gut gemacht.
Leider sind noch einige Fragen offen. Ich weiß zwar jetzt wie ich ein Record in eine Typisierte Datei rein und rausbekomme, aber nur bei einem normalen Record.

Quelltext
1:
var datei: file of record;                    

Wie mach ich das allerdings bei einem array auf record? Ich habe versucht

Quelltext
1:
2:
tormatrix :file of array [0..23]of array [0..9] of TTorDaten; 
AEvent: file of array [1..26] of TEvent;

Dann bekomme ich aber bei

Quelltext
1:
tormatrix[X,Y].Color := clWhite;                    

die Fehlermeldung Array-Typ erforderlich. Bei AEvent natürlich das selbe.
Woran liegt das?
Wenn ich übrigens

Quelltext
1:
2:
tormatrix :array [0..23]of array [0..9] of TTorDaten; 
AEvent: array [1..26] of TEvent;

deklariere, bekomme ich die Fehlermeldung Inkompatible Typen bei

Quelltext
1:
AssignFile(AEvent,'Event.sdf');                    

Und kann ich überhaupt gleichzeitig in zwei verschiedene typisierte Dateien schreiben? Ich denke mal schon, wenn nicht berichtigt mich bitte


Klabautermann - Fr 22.11.02 10:45

Hallo,

die Datei als solche, stellt dich eine Art Dynamisches Array da.
Du warum schreibst du die Elemente deines Arrays nicht einfach in einer Schleife raus?

Gruß
Klabautermann


sunday_2 - Fr 22.11.02 11:14

Hi Klabautermann,

Klabautermann hat folgendes geschrieben:
die Datei als solche, stellt dich eine Art Dynamisches Array da.
Du warum schreibst du die Elemente deines Arrays nicht einfach in einer Schleife raus?

Das versuche ich ja! :?
Leider klappt das nicht so, wie ich will. Ich poste dir mal das was ich bisher habe: Wäre echt nett, wenn du dir das mal anschaust. :wink:
Deklaration der Records

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
type
  TTorDaten = record
    Color: TColor;
    Name: String[5];
  end;
type
  TEvent = record
    Name: String[50];
    Zahl: String[10];
    Text: String[100];
    Grafik: String[100];
    Sound: String[100];
  end;

Variablendefinition:

Quelltext
1:
2:
tormatrix : array [0..23]of array [0..9] of TTorDaten;
AEvent:  array [1..26] of TEvent;

Speicherfunktion: Es sollen die Arrays komplett gefüllt gespeichert werden.

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:
procedure TSpieldefinition.b_sound_vorClick(Sender: TObject);
var i,j: integer;
    Datei:TextFile;
    datensatz: TEvent;
begin
        if SaveDialog1.Execute then
        begin
           AssignFile(Datei,SaveDialog1.Filename);
           Rewrite(Datei); //Datei erstellen

       for i:=1 to 26 do
        begin
        Seek(Datei,FilePos(Datei)-1);
        datensatz.Name := AEvent[i].Name;
        datensatz.Zahl := AEvent[i].Zahl;
        datensatz.Text := AEvent[i].Text;
        datensatz.Grafik := AEvent[i].Grafik;
        datensatz.Sound := AEvent[i].Sound;
        Write(Datei,datensatz);
        end;
        (*for i:= 1 to 23 do
        for j:= 1 to 9 do
        begin
           Write(Datei,tormatrix[i,j].Name);
           Write(Datei,tormatrix[i,j].color);
        end; *)
        end;
        CloseFile(Datei);
end;

tormatrix ist hier ausgeklammert. War ein erster Versuch. Will jetzt erstmal ein Array in einer Typisierten Datei speichern.

Bei OnCreate und OnDestroy des Formulars habe ich folgenden Code (Derzeit allerdings inaktiv)

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TSpieldefinition.FormCreate(Sender: TObject);
var I, J, K, X, Y: Integer;
begin
(*        //Anlegen der Datei Event.sdf
        AssignFile(AEvent,'Event.sdf');
        if FileExists('Event.sdf') then
           ReSet(AEvent)
        else
           ReWrite(AEvent);
        //Anlegen der Datei Tormatrix.sdf
        AssignFile(tormatrix,'Tormatrix.sdf');
        if FileExists('Tormatrix.sdf') then
           ReSet(tormatrix)
        else
           ReWrite(tormatrix);*)
 end;
procedure TSpieldefinition.FormDestroy(Sender: TObject);
begin
(*        CloseFile(AEvent);
        CloseFile(tormatrix);*)
end;


Kennst Du vieleicht ein Tutoral über die Vorgehensweise von Arrays in Typisierte Dateien schreiben?


Klabautermann - Fr 22.11.02 11:56

Hallo,
sunday_2 hat folgendes geschrieben:

Deklaration der Records

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
type
  TTorDaten = record
    Color: TColor;
    Name: String[5];
  end;
type
  TEvent = record
    Name: String[50];
    Zahl: String[10];
    Text: String[100];
    Grafik: String[100];
    Sound: String[100];
  end;


Da haben schon mal den ersten fehler. Wenn du das so machst, dann kann es dir Passoeren, das Dein Programm, wenn du es mal unter einer anderen DELPHI Version Kompilierst nicht mehr geht. Weil Borland die Blockgröße für Dateien geändert hat, deshalb solltest du die der Records Packen, dann werden die in der kleinst Möglichen größe gespeichert.

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
type
  TTorDaten = packed record
    Color: TColor;
    Name: String[5];
  end;
type
  TEvent = packed record
    Name: String[50];
    Zahl: String[10];
    Text: String[100];
    Grafik: String[100];
    Sound: String[100];
  end;



sunday_2 hat folgendes geschrieben:
Variablendefinition:
Speicherfunktion: Es sollen die Arrays komplett gefüllt gespeichert werden.

Quelltext
1:
2:
3:
procedure TSpieldefinition.b_sound_vorClick(Sender: TObject);
var i,j: integer;
    Datei:TextFile;


Da haben wir Fehler Nummer 2. wie Keldorn weiter oben bemerkte, darfst du hier kein Textfile verwenden sonder musst folgende Deklaration nehmen:

Quelltext
1:
Datei: FILE OF tEvent;                    

sunday_2 hat folgendes geschrieben:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
    datensatz: TEvent;
begin
        if SaveDialog1.Execute then
        begin
           AssignFile(Datei,SaveDialog1.Filename);
           Rewrite(Datei); //Datei erstellen

       for i:=1 to 26 do
        begin
        Seek(Datei,FilePos(Datei)-1);
        datensatz.Name := AEvent[i].Name;
        datensatz.Zahl := AEvent[i].Zahl;
        datensatz.Text := AEvent[i].Text;
        datensatz.Grafik := AEvent[i].Grafik;
        datensatz.Sound := AEvent[i].Sound;
        Write(Datei,datensatz);
        end;

Soweit sollte es nach den änderungen Klappen. Allerdings kannst du es doch vereinfachen, wenn du den Zwischenschritt über datensatzt weglässt:

Quelltext
1:
2:
for i:=1 to 26 do
  Write(Datei, AEvent[i]);

sunday_2 hat folgendes geschrieben:

Quelltext
1:
2:
3:
4:
5:
6:
        (*for i:= 1 to 23 do
        for j:= 1 to 9 do
        begin
           Write(Datei,tormatrix[i,j].Name);
           Write(Datei,tormatrix[i,j].color);
        end; *)

Soetwas kann nicht klappen, da werder tTorDaten.Name, noch tTorDaten.Color vom Typ tEvent sind. In eine Typisierte Datei kannst du nur Daten diese einen Typs schreiben (wie Keldorn ja schon feststellte).

Ich denke damit kommst du ersteinmal ein stückchen weiter.

Gruß
Klabautermann


sunday_2 - Fr 22.11.02 13:05

Hi Klabautermann,

vielen Dank, Du hast mir sehr geholfen. Wenn man sich das Ganze so anschaut, sieht das eigentlich auch ganz logisch aus.
Wenn es mal ne Wahl zum "Member of the Year" gibt, bist Du bestimmt ganz weit vorne. :wink:


wulfskin - Fr 22.11.02 14:33

Keldorn hat folgendes geschrieben:
@wulfskin; bisher war ich der ansicht, wenn du Fileof Record Typx verwendest, da nur auch records Typx lesen schreiben kannst.
Ich habe auch nicht gesagt, dass ich Fileof Record Typx benutzen möchte. Das hast du mich wohl falsch verstanden. Ich würde eine ganz normale untypisierte Datei vom Typ File estellen.

Gruß wulfskin!

P.S.: Wenn dich die Lösung auch noch interessiert, dann schreibe ich die auch noch!


Keldorn - Fr 22.11.02 16:43

wulfskin hat folgendes geschrieben:


P.S.: Wenn dich die Lösung auch noch interessiert, dann schreibe ich die auch noch!



ok, mach mal bitte, würd mich doch auch mal interessieren.

Frank