Entwickler-Ecke

Dateizugriff - Arbeit mit Listen - Fehler


Hellspike - Mi 02.03.05 18:07
Titel: Arbeit mit Listen - Fehler
Hallo!
Das ist mein erster beitrag hier und ich weiß nicht wo ich ihn sonst posten sollte.
Kann mir bitte jemand helfen?
Erstmal hier der Code:


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:
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:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;

type

  pDaten = ^tDaten;
  tDaten = record
    Begriff:string[20];
    next:pDaten;
  end;

  TForm1 = class(TForm)
    BegriffEingabe: TEdit;
    Button1: TButton;
    Button2: TButton;
    Panel1: TPanel;
    Label1: TLabel;
    Label3: TLabel;
    Memo1: TMemo;
    Label5: TLabel;
    Button3: TButton;
    SpeicherButton: TButton;
    Button5: TButton;
    Button6: TButton;
    procedure BegriffEingabeChange(Sender: TObject);
    procedure SpeicherButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure BegriffEingabeKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);

  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  SuchDatensatz:pDaten;
  Datensatz:pDaten;
  wahl:byte;
  leer:boolean;

implementation

{$R *.DFM}

procedure TForm1.BegriffEingabeChange(Sender: TObject);
var h:pDaten;
begin
     BegriffEingabe.Font.Color:=clBlack;
     SuchDatensatz^.Begriff := Begriffeingabe.Text;

     h:=Datensatz;
     while h<>NIL do begin
           if SuchDatensatz^.Begriff = h^.Begriff then Begriffeingabe.Font.Color:=clRed;
           h:=h^.next;
     end;
end;

procedure TForm1.SpeicherButtonClick(Sender: TObject);
var h,alt:pDaten;
    ersetzt:boolean;
    datei:file;
begin
     ersetzt:=false;

     AssignFile(datei,'test.txt');
     Rewrite(datei,1);

     if Datensatz = NIL then begin
        new(Datensatz);
        Datensatz^.next := NIL;
        move(SuchDatensatz^,Datensatz^,sizeof(tDaten));
        ersetzt:=true;
     end;

     h := Datensatz;
     while h<>NIL do begin
           if (h^.Begriff = SuchDatensatz^.Begriff)and not ersetzt then begin
              alt := h^.next;
              move(Suchdatensatz^, h^, sizeOf(tDaten));
              h^.next := alt;
              ersetzt := true;
           end;

           BlockWrite(datei, h^, sizeOf(tDaten));

           if (h^.next=NIL)and not ersetzt then begin
              new(h^.next);
              move(SuchDatensatz^,h^.next^,sizeof(tDaten));
           end;
           h := h^.next;
     end;

     CloseFile(Datei);
end;

procedure TForm1.FormCreate(Sender: TObject);
var datei:file;
    h:pDaten;
begin
     new(SuchDatensatz);
     SuchDatensatz^.next := NIL;

     AssignFile(datei,'test.txt');
     {$I-}
     Reset(datei,1);
     {$I+}

     if IOResult=0 then begin
        new(Datensatz);
        h := Datensatz;
        BlockRead(datei,h^,sizeOf(tDaten));
        while not eof(datei) do begin
              new(h^.next);
              h := h^.next;
              h^.next := NIL;
              BlockRead(datei,h^,sizeOf(tDaten));
        end;
        CloseFile(datei);
     end;
     

end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
     if Key=27 then close;
end;

procedure TForm1.BegriffEingabeKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
     if Key=27 then close;
end;




end.

hmm Kann mir bitte jemand dabei helfen?
Da steht immer ein/Out error is aufgetreten. Versuch hinter dem Dateiende zu lesen.
(Fehler liegt irgendwo beim blockwrite


Moderiert von user profile iconAXMD: Topic aus Off Topic verschoben am Mi 02.03.2005 um 18:12


AXMD - Mi 02.03.05 18:13

Hi :)!

Bitte ändere deinen Titel deines Beitrags so, dass er den Richtlinien entspricht. Dazu einfach den EDIT-Button rechts oben verwenden.

Richtlinien hat folgendes geschrieben:
1.2 Beiträge
Bitte formuliere den Betreff Deiner Beiträge so, dass andere Mitglieder anhand dieser bereits das eigentliche Thema festmachen können. Beiträge wie etwa "Eine Anfängerfrage" oder "Weiß jemand, wie das geht?" lassen den Leser im Unklaren darüber, was das Thema der Diskussion ist. [..]


Danke :)
AXMD


delfiphan - Mi 02.03.05 18:15

Hallo und :welcome:

1. Bitte ändere den Titel
2. Genaue Problembeschreibung bzw. wo tritt der Fehler genau auf? Was macht dein Programm überhaupt?

Du speicherst also mehrere Strings in ein File; dabei speicherst du die Pointers gleich mit. Das sollte zwar nicht schaden, da du die Pointers beim Lesen der Datei neu setzst; ich finde das aber trotzdem recht unsauber.
Du kannst mit einer TStringList Strings in eine Datei abspeichern und auch wieder laden. Du musst das Rad also nicht neu erfinden. Ausserdem fällt mir grad auf, dass du die Zeilen 125 und 126 vertauschen müsstest, damit du ein korrekter Abschluss der Pointerkette hast.

Was du alles selbst programmiert hast, d.h. String-Liste laden, speichern, suchen, etc. ist in Delphi alles schon enthalten. Dein Code liesse sich vermutlich auf wenige Zeilen Code verkürzen.


Hellspike - Mi 02.03.05 18:23

jau könnt ich schon aba unser Lehrer wills so.. des issn Projekt für die schule. :?


delfiphan - Mi 02.03.05 18:28

Dein Code lässt sich nicht direkt in unsere Delphis kopieren, wir müssten da zuerst alle Memos und Labels setzen und korrekt benennen; deswegen können wir auch nicht direkt eine Fehlersuche machen. Es hat hier wahrscheinlich auch keiner Lust, ganze Quelltexte durchzugehn. Bitte gib uns deshalb die genaue Fehlermeldung mit Zeilennummer an.


Hellspike - Mi 02.03.05 18:35

Also Zeile 126 scheints zu hacken (da zeigt der grüne Pfeil hin)
Meldung:
Im Projekt Projekt1.exe ist eine Exception der Klasse EinOutError Aufgetreten. Meldung:"Versuch hinter dem Dateiende zu lesen." Prozess wurde angehalten. Mit einzelne Anweisung oder start fortsetzen. :?


AXMD - Mi 02.03.05 18:40

Ein paar Kommentare zu den Variablen und dem, was du machst, wären nicht schlecht. Der Blockread-Aufruf ansich stimmt ja, aber beim Speichern habe ich einige Schwierigkeiten deinen Code zu verstehen

AXMD


jasocul - Mi 02.03.05 18:43

Ein Blick in die Delphi-Hilfe hätte genügt:
Zitat:
procedure BlockRead(var F: File; var Buf; Count: Integer [; var AmtTransferred: Integer]);

Beschreibung

F ist eine untypisierte Dateivariable, Buf eine beliebige Variable, Count ein Integer-Ausdruck und AmtTransferred eine optionale Integer-Variable.

BlockRead liest ab dem ersten von Buf belegten Byte bis zu Count Datenblöcke aus der Datei F in den Speicher. Die tatsächliche Anzahl der vollständig gelesenen Blöcke (kleiner oder gleich Count) wird in der Variablen AmtTransferred zurückgegeben.

Der ganze übertragene Block belegt höchstens Count * RecSize Bytes. RecSize ist die beim Öffnen der Datei angegebene Blockgröße (oder 128, falls keine Größe angegeben wurde).

Wird der gesamte Block übertragen, ist AmtTransferred mit Count identisch.

Ist AmtTransferred kleiner als Count, wurde vor Beendigung der Übertragung das Dateiende erreicht. In diesem Fall gibt AmtTransferred die Anzahl der vollständig gelesenen Blöcke zurück, wenn die Datenblockgröße der Datei größer als 1 ist.

Wird AmtTransferred nicht angegeben, tritt ein E/A-Fehler auf, wenn die Anzahl der gelesenen Datenblöcke nicht mit Count identisch ist. Wenn die Compiler-Direktive $I+ aktiv ist, lösen Fehler eine EInOutError-Exception aus.

Die beiden letzten Absätze beschreiben dein Problem und wie du es beheben kannst.


delfiphan - Mi 02.03.05 18:47

@jasocul: Das löst das Problem ja nicht. Die Fehlermeldung wurde uns ja angegeben :)

Offensichtlich stimmt die Dateigrösse von test.txt einfach nicht (muss Vielfaches von SizeOf(tDaten) sein). Hast du sie irgendwo editiert? Dein test.txt ist ja keine txt Datei, du musst also aufpassen wenn du die Datei in einem externen Programm bearbeitest!

du kannst mit:

Delphi-Quelltext
1:
BlockRead(datei,h^,sizeOf(tDaten),Gelesene_Bytes);                    

herausfinden, wieviele Bytes wirklich gelesen wurden.
Es sollte dann auch keine Exceptions mehr geben. Falls SizeOf(tDaten) <> Gelesene_Bytes ist, dann stimmt einfach die Dateigrösse nicht.

PS: Du solltest nach jedem "BlockRead" das h^.next auf nil setzen. Sonst kriegst du bei manchen Fällen Probleme.