![]() |
Einfaches Abspeichern in externer Datei // Schülerverwaltung
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich bin gerade dabei ein Programm zu schreiben, mit dessen Hilfe ich Schülerdaten (Schülernr., Name, Vorname, Klasse, usw.) in einer Datei abspeichern kann, sodass diese nach Schließen und erneutem Öffnen des Programms über den Klick eines Buttons wieder eingelesen werden und wieder verfügbar sind. Soweit so gut. Allerdings werden, wenn ich Daten zu verschiedenen Schülern gespeichert habe, und mich vergewissert habe, dass diese auch wieder über die Schülernummer aufrufbar sind, diese nicht geladen bzw. wieder korrekt ausgegeben, wenn ich das Programm neustarte. Ich würde mich sehr freuen, wenn ihr mich ein bisschen bei der Fehlersuche unterstützen könntet. Im Unterricht wurden uns jedenfalls heute einfach diese ganzen assignfile-Sachen an den Kopf geknallt. Der Test auf IO-Fehler ist übrigens ein Pflichtelement des Programms. Hier mal der Quelltext:
Delphi-Quellcode:
Im Anhang habe ich noch mal ein Bild, das zeigt, wie das Programm so aussieht.
unit zeugnis;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) ButtonSpeichern: TButton; ButtonAuslesen: TButton; ButtonBeenden: TButton; EditSNr: TEdit; EditName: TEdit; EditVorname: TEdit; EditGebDat: TEdit; EditGebOrt: TEdit; EditOrt: TEdit; EditKlasse: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; Label6: TLabel; Label7: TLabel; Label8: TLabel; Label9: TLabel; ButtonClear: TButton; EditDatensatzNr: TEdit; Label10: TLabel; ButtonSchuelerDaten: TButton; Label11: TLabel; ButtonEintragSpeichern: TButton; procedure ButtonBeendenClick(Sender: TObject); procedure ButtonSpeichernClick(Sender: TObject); procedure ButtonAuslesenClick(Sender: TObject); procedure ButtonClearClick(Sender: TObject); procedure ButtonSchuelerDatenClick(Sender: TObject); procedure ButtonEintragSpeichernClick(Sender: TObject); end; tSNr = string[5]; tName = string[20]; tVorname = string[15]; tGebDat = string[10]; tGebOrt = string[15]; tOrt = string[15]; tKlasse = string[4]; tSchueler = record Nr :tSNr; //Schuelernummer bzw. Datensatznummer Name :tName; //Schuelername Vorname :tVorname; //Schuelervorname Geburtsort :tGebOrt; //Geburtsort GebDat :tGebDat; //Geburtsdatum Ort :tOrt; //Wohnort Klasse :tKlasse; //Klasse end; const Datenpfad='Schueler.dta'; var Form1: TForm1; Datensatz: array[1..99999] of tSchueler; //Array für Schuelerdatensätze num: integer; //Datensatznummer f: file of tSchueler; implementation {$R *.dfm} procedure Kontrolle; //Prozedur zum Test, ob einige der bekannten IO-Fehler gefunden werden begin case IOResult of 2: begin showmessage ('Datei nicht vorhanden.' +#13+ 'Datei wird angelegt'); rewrite(f); closeFile(f); end; 3: showmessage ('Ungueltiger Dateiname/Pfad'); 5: showmessage ('Dateizugriff verweigert.'); 21: showmessage ('Laufwerk nicht bereit!'); end; end; procedure TForm1.ButtonSpeichernClick(Sender: TObject); //Datenbank abspeichern var i:integer; begin Assignfile (f,Datenpfad); {$I-} reset (f); {$T+} Kontrolle; if IOResult=0 then begin for i:=1 to 99999 do write (f, Datensatz[i]); closefile (f); end; end; procedure TForm1.ButtonAuslesenClick(Sender: TObject); //Datenbank laden var i:integer; begin Assignfile (f,Datenpfad); Kontrolle; if IOResult=0 then begin for i:=1 to 99999 do read (f, Datensatz[i]); closefile (f); end; end; procedure TForm1.ButtonEintragSpeichernClick(Sender: TObject); //Schüler-Eintrag speichern var fehler: boolean; //Wird true gesetzt, wenn ein Eingabefeld leer ist begin fehler:=false; num:=1; if length(EditSNr.Text)=0 then fehler:=true else begin num:=StrToInt(EditSNr.Text); if length(EditSNr.Text)<>0 then Datensatz[num].Nr:= EditSNr.Text else fehler:=true; if length(EditName.Text)<>0 then Datensatz[num].Name:= EditName.Text else fehler:=true; if length(EditVorname.Text)<>0 then Datensatz[num].Vorname:= EditVorname.Text else fehler:=true; if length(EditGebOrt.Text)<>0 then Datensatz[num].Geburtsort:= EditGebOrt.Text else fehler:=true; if length(EditGebDat.Text)<>0 then Datensatz[num].GebDat:= EditGebDat.Text else fehler:=true; if length(EditOrt.Text)<>0 then Datensatz[num].Ort:= EditOrt.Text else fehler:=true; if length(EditKlasse.Text)<>0 then Datensatz[num].Klasse:= EditKlasse.Text else fehler:=true; end; if fehler=true then showmessage('Bitte füllen Sie alle Felder aus!') else begin showmessage('Eintrag erfolgreich gespeichert'); end; end; procedure TForm1.ButtonClearClick(Sender: TObject); //Felder leeren begin EditSNr.Text:=''; EditName.Text:=''; EditVorname.Text:=''; EditGebOrt.Text:=''; EditGebDat.Text:=''; EditOrt.Text:=''; EditKlasse.Text:=''; end; procedure TForm1.ButtonSchuelerDatenClick(Sender: TObject); //Daten zu einem Schüler anzeigen var i: integer; //Datensatznummer begin i:=StrToInt(EditDatensatzNr.Text); if (length(EditDatensatzNr.Text)<>0) and (length(EditDatensatzNr.Text)<=5) then begin EditSNr.Text:=Datensatz[i].Nr; EditName.Text:=Datensatz[i].Name; EditVorname.Text:=Datensatz[i].Vorname; EditGebOrt.Text:=Datensatz[i].GeburtsOrt; EditGebDat.Text:=Datensatz[i].GebDat; EditOrt.Text:=Datensatz[i].Ort; EditKlasse.Text:=Datensatz[i].Klasse; end else showmessage('Bitte eine gültige Datensatz-Nummer eintragen'); end; procedure TForm1.ButtonBeendenClick(Sender: TObject); //Programm beenden begin close; end; end. Vielen Dank Jan |
Re: Einfaches Abspeichern in externer Datei // Schülerverwal
Guten Abend,
ich würde die Prozedure Kontrolle zu einer Funktion umbauen:
Delphi-Quellcode:
und sie dann so einsetzen:
function Kontrolle:Boolean; //Prozedur zum Test, ob einige der bekannten IO-Fehler gefunden werden
begin result := false; case IOResult of 0: result := true; 2: begin showmessage ('Datei nicht vorhanden.' +#13+ 'Datei wird angelegt'); rewrite(f); // closeFile(f); // wenn Du die Datei erstellt hast nicht gleich wieder schließen Du willst ja noch etwas abspeichern result := true; end; 3: showmessage ('Ungueltiger Dateiname/Pfad'); 5: showmessage ('Dateizugriff verweigert.'); 21: showmessage ('Laufwerk nicht bereit!'); end; end;
Delphi-Quellcode:
procedure TForm1.ButtonSpeichernClick(Sender: TObject); //Datenbank abspeichern
var i:integer; begin Assignfile (f,Datenpfad); {$I-} reset (f); {$I+} if Kontrolle then begin for i:=1 to 99999 do write (f, Datensatz[i]); closefile (f); end; end; denn in Deinem Konstrukt wird IOResult immer 0 sein. Denn wenn IOResult einmal abgefragt wurde wird IOError gelöscht: Aus der Hilfe: Zitat:
[edit]
Delphi-Quellcode:
hier vielleicht einen absoluten Pfad zur Datei angeben.
const Datenpfad='Schueler.dta';
[edit2]
Delphi-Quellcode:
procedure TForm1.ButtonAuslesenClick(Sender: TObject); //Datenbank laden
var i:integer; begin i:=1; Assignfile (f,Datenpfad); {$I-} reset(f) {$I+} if Kontrolle then begin while not eof(f) do begin read(f, Datensatz[i]); inc(i); end; end; closefile (f); end; end; Grüße Klaus |
Re: Einfaches Abspeichern in externer Datei // Schülerverwal
Moin, Moin.
Delphi-Quellcode:
PS:
procedure TForm1.ButtonSpeichernClick(Sender:TObject);
var i : Integer; f : file of tSchueler; begin assignfile(f,Datenpfad); {$I-} rewrite (f); {$I+} .. procedure TForm1.ButtonLadenClick(Sender:TObject); var i : Integer; f : file of tSchueler; begin assignfile(f,Datenpfad); {$I-} reset (f); {$I+} .. a) So wenig wie möglich global deklarieren! b) "Datensatz: array[1..99999] of tSchueler;" ist schon heftig! Kennt ihr noch keine dynamischen Arrays? |
Re: Einfaches Abspeichern in externer Datei // Schülerverwal
Hallo,
statt
Delphi-Quellcode:
würde ich
tSchueler = record
Delphi-Quellcode:
schreiben und die alte Datei löschen..
tSchueler = packed record
Ausserdem kannst du mit FileExists prüfen, ob die Datei vorhanden ist und dann entweder Reset oder ReWrite benutzen. Das ersetzt natürlich das IOResult nicht. Bei procedure TForm1.ButtonEintragSpeichernClick fiel mir noch was auf. Was passiert, wenn der letzte Editor leer ist ... Du hast alle anderen Werte schon in den Datensatz eingetragen und ereugst zum Schluss einen Fehler. Die anderen Werte stehen aber trotzdem schon drin ! Besser wäre hier
Delphi-Quellcode:
fehler:= (EditName.Text='') or
(EditOrt.Text='') or usw. (EditOrt.EditKlasse=''); Heiko |
Re: Einfaches Abspeichern in externer Datei // Schülerverwal
Hallo Jan,
die wichtigste Antwort hat Dir wohl Klaus schon gegeben:
Delphi-Quellcode:
Bei Deiner Lösung (for i:=0 to 99999....) hast immer das Problem, daß eine teilweise beschädigte Datei das Lesen unmöglich macht.
while not eof(f) do
begin read(f, Datensatz[i]); inc(i); end; Mir behagt die Definition des records nicht
Delphi-Quellcode:
Ich würde mit fixen Satzlängen arbeiten:
tSNr = string[5];
tName = string[20]; tVorname = string[15]; tGebDat = string[10]; tGebOrt = string[15]; tOrt = string[15]; tKlasse = string[4]; tSchueler = record Nr :tSNr; //Schuelernummer bzw. Datensatznummer Name :tName; //Schuelername Vorname :tVorname; //Schuelervorname Geburtsort :tGebOrt; //Geburtsort GebDat :tGebDat; //Geburtsdatum Ort :tOrt; //Wohnort Klasse :tKlasse; //Klasse end;
Delphi-Quellcode:
Wobei allerdings ein leerer Datensatz und ein mit Leerzeichen gefüllter Datensatz nicht zu unterscheiden wären.
tSNr = Array of Char[1..5];
tName = Array of Char[1..20]; tVorname = Array of Char[1..15]; tGebDat = Array of Char[1..10]; tGebOrt = Array of Char[1..15]; tOrt = Array of Char[1..15]; tKlasse = Array of Char[1..4]; tSchueler = record Nr :tSNr; //Schuelernummer bzw. Datensatznummer Name :tName; //Schuelername Vorname :tVorname; //Schuelervorname Geburtsort :tGebOrt; //Geburtsort GebDat :tGebDat; //Geburtsdatum Ort :tOrt; //Wohnort Klasse :tKlasse; //Klasse end; (Ok da kann man noch eine #0 als Begrenzer einsetzen, verliert aber ein Datenzeichen) Wenn Du dann noch ein #13#10 als Abschluß Deines Records hinein packst, ist die Datei problemlos mit jedem Editor les- und kontrollierbar. Gruß K-H |
Re: Einfaches Abspeichern in externer Datei // Schülerverwal
@p80286: das sind ShortStrings und die haben immer eine fixe Größe :zwinker:
String[8] ist ein AnsiString mit maximal 8 Zeichen Inhalt, die Größe im Speicher liegt immer bei genau 9 Byte und im Gegensatz zu den "normalen" Strings gibt es hier keinen internen Pointer. |
Re: Einfaches Abspeichern in externer Datei // Schülerverwal
@himitsu
Pardon ungenau ausgedrückt. wenn Du z.B. "Ralf" abspeichern willst, dann steht hinterher in der Datei #4Ralfxxxxxxxxxxxxxx wobei jedes x für irgendein beliebiges Zeichen steht. Das ist bei meinem Vorschlag nicht der Fall, da ja jedes Feld vorher initialisiert wird/werden sollte.(Hab ich auch vergessen zu schreiben) Das es ein paar intelligentere Formate zum Abspeichern gibt, lassen wir mal aussen vor. Gruß K-H |
Re: Einfaches Abspeichern in externer Datei // Schülerverwal
Hihi, genau diese Aufgabe hatte ich am Anfang meines Studiums auch auf dem Tisch liegen.
Statt deines Arrays würde ich eine doppelt verkettete Liste verwenden und beim Auslesen auf EOF prüfen. Die hat den Vorteil, dass du nicht gebunden bist. Aber ist Geschmackssache. |
Re: Einfaches Abspeichern in externer Datei // Schülerverwal
Also einen ShortString kann man auch initialisieren, wenn man denn will.
|
Re: Einfaches Abspeichern in externer Datei
Sorry, dass ich mich nicht gemeldet habe.
Also ich habe mal versucht eure Vorschläge mit einzuarbeiten. Wenn ich jetzt allerdings auf das Feld "Datenbank Laden" klicke erhalte ich eine Fehlermeldung in neuem Fenster: "Project raised exception class EInOutError with message 'Read beyond end of file'. Process stopped. Use step or run to continue" So sieht mein Quelltext jetzt aus:
Delphi-Quellcode:
Ich habe noch nicht ganz verstanden, wie ihr das mit den dynamische Arrays meint. Ich habe jetzt erstaml aus Testzwecken die Schülerzahl auf 10 gesenkt.
unit zeugnis;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) ButtonSpeichern: TButton; ButtonAuslesen: TButton; ButtonBeenden: TButton; EditSNr: TEdit; EditName: TEdit; EditVorname: TEdit; EditGebDat: TEdit; EditGebOrt: TEdit; EditOrt: TEdit; EditKlasse: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; Label6: TLabel; Label7: TLabel; Label8: TLabel; Label9: TLabel; ButtonClear: TButton; EditDatensatzNr: TEdit; Label10: TLabel; ButtonSchuelerDaten: TButton; Label11: TLabel; ButtonEintragSpeichern: TButton; procedure ButtonBeendenClick(Sender: TObject); procedure ButtonSpeichernClick(Sender: TObject); procedure ButtonAuslesenClick(Sender: TObject); procedure ButtonClearClick(Sender: TObject); procedure ButtonSchuelerDatenClick(Sender: TObject); procedure ButtonEintragSpeichernClick(Sender: TObject); end; tSNr = string[5]; tName = string[20]; tVorname = string[15]; tGebDat = string[10]; tGebOrt = string[15]; tOrt = string[15]; tKlasse = string[4]; tSchueler = record Nr :tSNr; //Schuelernummer bzw. Datensatznummer Name :tName; //Schuelername Vorname :tVorname; //Schuelervorname Geburtsort :tGebOrt; //Geburtsort GebDat :tGebDat; //Geburtsdatum Ort :tOrt; //Wohnort Klasse :tKlasse; //Klasse end; const Datenpfad='Schueler.dta'; var Form1: TForm1; Datensatz: array[1..10] of tSchueler; //Array für Schuelerdatensätze f: file of tSchueler; implementation {$R *.dfm} function Kontrolle:Boolean; //Prozedur zum Test, ob einige der bekannten IO-Fehler gefunden werden begin result := false; case IOResult of 0: result := true; 2: begin showmessage ('Datei nicht vorhanden.' +#13+ 'Datei wird angelegt'); rewrite(f); result := true; end; 3: showmessage ('Ungueltiger Dateiname/Pfad'); 5: showmessage ('Dateizugriff verweigert.'); 21: showmessage ('Laufwerk nicht bereit!'); end; end; procedure TForm1.ButtonSpeichernClick(Sender: TObject); //Datenbank abspeichern var i:integer; begin Assignfile (f,Datenpfad); {$I-} reset (f); {$I+} if Kontrolle then begin for i:=1 to 10 do write (f, Datensatz[i]); closefile (f); end; end; procedure TForm1.ButtonAuslesenClick(Sender: TObject); //Datenbank laden var i:integer; begin i:=1; Assignfile (f,Datenpfad); {$I-} reset(f); {$I+} if Kontrolle then begin while not eof(f) do begin read(f, Datensatz[i]); inc(i); end; end; closefile (f); end; procedure TForm1.ButtonEintragSpeichernClick(Sender: TObject); //Schüler-Eintrag speichern var fehler: boolean; //Wird true gesetzt, wenn ein Eingabefeld leer ist i:integer; begin fehler:=false; i:=1; if length(EditSNr.Text)=0 then fehler:=true else begin i:=StrToInt(EditSNr.Text); if length(EditSNr.Text)<>0 then Datensatz[i].Nr:= EditSNr.Text else fehler:=true; if length(EditName.Text)<>0 then Datensatz[i].Name:= EditName.Text else fehler:=true; if length(EditVorname.Text)<>0 then Datensatz[i].Vorname:= EditVorname.Text else fehler:=true; if length(EditGebOrt.Text)<>0 then Datensatz[i].Geburtsort:= EditGebOrt.Text else fehler:=true; if length(EditGebDat.Text)<>0 then Datensatz[i].GebDat:= EditGebDat.Text else fehler:=true; if length(EditOrt.Text)<>0 then Datensatz[i].Ort:= EditOrt.Text else fehler:=true; if length(EditKlasse.Text)<>0 then Datensatz[i].Klasse:= EditKlasse.Text else fehler:=true; end; if fehler=true then showmessage('Bitte füllen Sie alle Felder aus!') else begin showmessage('Eintrag erfolgreich gespeichert'); end; end; procedure TForm1.ButtonClearClick(Sender: TObject); //Felder leeren begin EditSNr.Text:=''; EditName.Text:=''; EditVorname.Text:=''; EditGebOrt.Text:=''; EditGebDat.Text:=''; EditOrt.Text:=''; EditKlasse.Text:=''; end; procedure TForm1.ButtonSchuelerDatenClick(Sender: TObject); //Daten zu einem Schüler anzeigen var i: integer; //Datensatznummer begin i:=StrToInt(EditDatensatzNr.Text); if (length(EditDatensatzNr.Text)<>0) and (length(EditDatensatzNr.Text)<=5) then begin EditSNr.Text:=Datensatz[i].Nr; EditName.Text:=Datensatz[i].Name; EditVorname.Text:=Datensatz[i].Vorname; EditGebOrt.Text:=Datensatz[i].GeburtsOrt; EditGebDat.Text:=Datensatz[i].GebDat; EditOrt.Text:=Datensatz[i].Ort; EditKlasse.Text:=Datensatz[i].Klasse; end else showmessage('Bitte eine gültige Datensatz-Nummer eintragen'); end; procedure TForm1.ButtonBeendenClick(Sender: TObject); //Programm beenden begin close; end; end. Vielen Dank im Voraus Jan |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:57 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz