Autor Beitrag
Bofrost_Mann
Hält's aus hier
Beiträge: 15

Win XP
Delphi 5, Delphi 2005
BeitragVerfasst: Sa 02.02.08 22:14 
Hallo, ich bin vollkommen neu auf dem Gebiet von FileStreams und möchte zwei Records in eine Datei schreiben und diese natürlich auch wieder lesen. Ich bin gerade dabei das ganze rein funktional zu testen um mit dem ganzen dann später den Datenaustausch für ein schon bestehendes Programm zu organisieren werden, was bis jetzt auf Basis von Textdateien funktioniert.

Starte ich das Programm in Delphi scheint das Speichern und Laden auch zu funktionieren, doch will ich es beenden erscheint eine Fehlermeldung:

"mit ...\Project1.exe trat ein Problem auf ... access violation at ... write of adress ...".

Starte ich die compilierte *.exe erscheint keine Fehlermeldung beim schließen, wenn die Datei mit der selpen Compilierung erstellt wurde.

Was hat es mit dieser Meldung auf sich bzw. wo liegt der Fehler?

-----

Wurde die Datei mit einer älteren Compilierung erstellt und soll sie geladen werden, erscheint eine Fehlermeldung. Die Frage hierzu: ist es möglich auch Dateien älterer Compilierungen wieder einzulesen.

ausblenden 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:
procedure TForm1.SaveVars; //Buch in Datei schreiben
var
   Stream:TFileStream;
   SchreibBuch: array [1..2of Katalog;
begin
  SchreibBuch[1]:=Buch[1];
  SchreibBuch[2]:=Buch[2];

  Stream:=TFileStream.Create('C:\Speicher\Test.adb', fmCreate);
  try
    Stream.WriteBuffer(SchreibBuch,SizeOf(SchreibBuch));
    Stream.WriteBuffer(ProgrammVersion,SizeOf(ProgrammVersion));
  finally
    Stream.Free;
  end;  
end;
 
procedure TForm1.LoadVars; //LeseBuch aus Datei lesen
var
   Stream:TFileStream;
begin
  Stream:=TFileStream.Create('C:\Speicher\Test.adb', fmOpenRead);
  try  
    Stream.ReadBuffer(LeseBuch,SizeOf(LeseBuch));
    Stream.ReadBuffer(ProgrammVersion,SizeOf(ProgrammVersion));
  finally  
    Stream.Free;  
  end;
end;


Schonmal Danke für Eure Antworten.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 04.02.08 16:58 
Moin und :welcome: im Forum!

user profile iconBofrost_Mann hat folgendes geschrieben:
Was hat es mit dieser Meldung auf sich bzw. wo liegt der Fehler?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.SaveVars; //Buch in Datei schreiben
var
   Stream:TFileStream;
   SchreibBuch: array [1..2of Katalog;
begin
Um deine Frage beantworten zu können, benötigen wir noch die Deklaration des Typs Katalog.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Erichgue
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 86

Win XP/2000/7
TurboPacal 7.0; Delphi 2/5/7; BDS 2006/2010/XE6; C#; MSSQl 2000
BeitragVerfasst: Mo 04.02.08 17:35 
Zitat:
Starte ich das Programm in Delphi scheint das Speichern und Laden auch zu funktionieren, doch will ich es beenden erscheint eine Fehlermeldung:


Was machst du denn beim Beenden?
Zeigt mal etwas Code!

Erich
Bofrost_Mann Threadstarter
Hält's aus hier
Beiträge: 15

Win XP
Delphi 5, Delphi 2005
BeitragVerfasst: Di 05.02.08 17:55 
hier mal der komplette code der unit ... diese unit soll erstmal nur "symbolcharakter" haben und rein funktionell einwandfrei arbeiten ...

ausblenden volle Höhe 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:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Edit5: TEdit;
    Edit6: TEdit;
    Edit7: TEdit;
    Edit8: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);

  private
     procedure LoadVars; //Laden
     procedure SaveVars; //Speichern

  public
    { Public-Deklarationen }
  end;

type Katalog=record //Daten der einzelnen Personen
  Name: string;
  Vorname: string;
end;

type Version=record //Programmversion
  Programm: integer;
  Adressbuch: integer;
end;

var
  Form1: TForm1;
  Buch: array [1..2of Katalog;
  LeseBuch: array [1..2of Katalog;

  ProgrammVersion: Version;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
buch[1].name:='nachname1';
buch[1].vorname:='rufname1';

buch[2].name:='nachname2';
buch[2].vorname:='rufname2';

ProgrammVersion.Programm:=1;
ProgrammVersion.Adressbuch:=0;

edit1.text:=buch[1].name;
edit2.text:=buch[1].vorname;
edit3.text:=buch[2].name;
edit4.text:=buch[2].vorname;
end;

procedure TForm1.SaveVars; //Buch in Datei schreiben
var
   Stream:TFileStream;
   SchreibBuch: array [1..2of Katalog;
begin
  SchreibBuch[1]:=Buch[1];
  SchreibBuch[2]:=Buch[2];

  Stream:=TFileStream.Create('C:\Speicher\Test.adb', fmCreate);
  try
    Stream.WriteBuffer(SchreibBuch,SizeOf(SchreibBuch));
    Stream.WriteBuffer(ProgrammVersion,SizeOf(ProgrammVersion));
  finally
    Stream.Free;
  end;  
end;
 
procedure TForm1.LoadVars; //LeseBuch aus Datei lesen
var
   Stream:TFileStream;
begin
  Stream:=TFileStream.Create('C:\Speicher\Test.adb', fmOpenRead);
  try  
    Stream.ReadBuffer(LeseBuch,SizeOf(LeseBuch));
    Stream.ReadBuffer(ProgrammVersion,SizeOf(ProgrammVersion));
  finally  
    Stream.Free;  
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
savevars;
button1.enabled:=false;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
loadvars;

edit5.text:=LeseBuch[1].name;
edit6.text:=LeseBuch[1].vorname;
edit7.text:=LeseBuch[2].name;
edit8.text:=LeseBuch[2].vorname;
end;

end.
Keldorn
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 2266
Erhaltene Danke: 4

Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
BeitragVerfasst: Di 05.02.08 18:18 
Hallo

in deinem Record ist ein string enthalten, da wird das nix, weil die eigentliche Länge nicht bekannt ist.
ausblenden Delphi-Quelltext
1:
SizeOf(SchreibBuch));					

laß dir das mal in einer messagebox anzeigen.

Entweder, du nimmst strings mit einer festen länge
ausblenden Delphi-Quelltext
1:
2:
3:
4:
type Katalog=record //Daten der einzelnen Personen  
  Name: string[30];  
  Vorname: string[30];  
end;


oder besser, such mal im Forum, Fragen zu strings und stream gibts recht häufig, oder du guggst mal nach Suche in: Delphi-Forum, Delphi-Library TREADER und Suche in: Delphi-Forum, Delphi-Library TWRITER, damit machst du dir das Leben auch leichter.

Gruß Frank

_________________
Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
Bofrost_Mann Threadstarter
Hält's aus hier
Beiträge: 15

Win XP
Delphi 5, Delphi 2005
BeitragVerfasst: Di 05.02.08 21:44 
Danke an alle, für Eure Tipps. Ich hab in Katalog die Strings jetzt als shortstring deklariert und bekomm auch keine fehler mehr. Das Einlesen von Dateien älterer Compilierungen scheint auch Problemlos zu funktionieren.
Bofrost_Mann Threadstarter
Hält's aus hier
Beiträge: 15

Win XP
Delphi 5, Delphi 2005
BeitragVerfasst: Di 05.02.08 22:24 
Habe doch noch ein kleines Problem: kann ich das ganze auch dynamisch vereinbaren? D.h. ein Array mit dynamischer Länge Speichern und dann auch wieder lesen?

Folgender Versuch brachte Fehler:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TForm1.SaveVars; //Buch in Datei schreiben
var
   Stream:TFileStream;
   SchreibBuch: array of Katalog;
begin

  setlength(Schreibbuch, 3);

  SchreibBuch[1]:=Buch[1];
  SchreibBuch[2]:=Buch[2];
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 05.02.08 22:45 
Moin!

user profile iconBofrost_Mann hat folgendes geschrieben:
kann ich das ganze auch dynamisch vereinbaren? D.h. ein Array mit dynamischer Länge Speichern und dann auch wieder lesen?
Wozu überhaupt dieses Array als Umweg zum Speichern? :gruebel:

Schreib doch einfach direkt die records der Reihe nach in den Stream und gut. :nixweiss: :idea:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Keldorn
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 2266
Erhaltene Danke: 4

Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
BeitragVerfasst: Mi 06.02.08 09:59 
Hallo,

wenn du nur shortstring hast, dann kommst du über die Länge des Streams und Größe deines Records auf die Anzahl der gespeicherten Daten.

Wenn du es völlig dynamisch haben willst, dann schreib als erstes die anzahl in den stream und danach dann die daten, umgedreht dann genauso.

Als Anregung dieser Thread

Gruß Frank

_________________
Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
Bofrost_Mann Threadstarter
Hält's aus hier
Beiträge: 15

Win XP
Delphi 5, Delphi 2005
BeitragVerfasst: Mi 06.02.08 14:31 
Hallo, und nochmal Danke an alle für die schnellen Antworten. Habe das Speichern und Laden jetzt über Treader und Twriter organisiert (thx@ Keldorn). Ich hänge den jetzigen Quelltext nocheinmal an, falls andere ähnliche Probleme haben und Anregungen suchen.
ausblenden volle Höhe 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:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Edit5: TEdit;
    Edit6: TEdit;
    Edit7: TEdit;
    Edit8: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);

  private
     procedure LoadVars; //Laden
     procedure SaveVars; //Speichern
     

  public
    { Public-Deklarationen }
  end;

type Katalog=record //Daten der einzelnen Personen
  Name: string;
  Vorname: string;
end;

type Version=record //Programmversion
  Programm: integer;
  Adressbuch: integer;
end;

var
  Form1: TForm1;
  Buch: array of Katalog;
  LeseBuch: array of Katalog;

  ProgrammVersion: Version;
  LeseProgrammVersion: Version;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
setlength(buch, 3);

buch[0].name:='';
buch[0].vorname:='';

buch[1].name:='nachname1';
buch[1].vorname:='rufname1';

buch[2].name:='nachname2';
buch[2].vorname:='rufname2';

ProgrammVersion.Programm:=1;
ProgrammVersion.Adressbuch:=0;

edit1.text:=buch[1].name;
edit2.text:=buch[1].vorname;
edit3.text:=buch[2].name;
edit4.text:=buch[2].vorname;
end;

procedure TForm1.SaveVars; //Buch in Datei schreiben
var
   Stream:TFileStream;
   SchreibBuch: array of Katalog;
   i: integer;
begin

  setlength(Schreibbuch, length(buch)); //Länge von Schreibbuch setzen

  for i:=0 to length(buch)-1 do SchreibBuch[i]:=Buch[i]; //Tiefenkopie

  Stream:=TFileStream.Create('C:\Speicher\Test.adb', fmCreate); //Datei erzeugen

  try

     begin
          with Twriter.create(Stream,1024do
               begin
                    try
                       begin
                            writeinteger(ProgrammVersion.Programm); //Programmversion schreiben
                            writeinteger(ProgrammVersion.Adressbuch);

                            writeinteger(length(schreibBuch)); //anzahl schreiben

                            for i:=0 to length(schreibBuch)-1 do
                                begin
                                     writestring(schreibbuch[i].Name);
                                     writestring(schreibbuch[i].Vorname);
                                end;
                       end;
                    finally
                           free;
                    end;
              end;
     end;

  finally

    Stream.Free;

  end;

end;
 
procedure TForm1.LoadVars; //LeseBuch aus Datei lesen
var
   Stream:TFileStream;
   i:integer;
   anzahl: integer;
begin

  Stream:=TFileStream.Create('C:\Speicher\Test.adb', fmOpenRead);

  try

    begin
        with Treader.create(Stream,1024do
             begin
                  try
                     begin
                          LeseProgrammVersion.Programm:=readinteger; //Programmversion auslesen
                          LeseProgrammVersion.Adressbuch:=readinteger;

                          anzahl:=readinteger; //anzahl lesen
                          setlength(lesebuch, anzahl);  //array-größe festlegen

                          for i:=0 to anzahl-1 do
                              begin
                                   lesebuch[i].Name:=readstring;
                                   lesebuch[i].Vorname:=readstring;
                              end;
                     end;
                  finally
                         free;
                  end;
             end;
   end;

  finally

    Stream.Free;

  end;

end;





procedure TForm1.Button1Click(Sender: TObject);
begin
savevars;
button1.enabled:=false;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
loadvars;

Form1.caption:='Kontakte Version '+inttostr(LeseProgrammVersion.Programm)+'.'+inttostr(LeseProgrammVersion.Adressbuch);

edit5.text:=LeseBuch[1].name;
edit6.text:=LeseBuch[1].vorname;
edit7.text:=LeseBuch[2].name;
edit8.text:=LeseBuch[2].vorname;
end;

end.


Liebe Grüße

Der Bofrost Mann
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 07.02.08 12:20 
Moin!

Nochmal: :roll:
user profile iconBofrost_Mann hat folgendes geschrieben:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
//...
procedure TForm1.SaveVars; //Buch in Datei schreiben
//...
  setlength(Schreibbuch, length(buch)); //Länge von Schreibbuch setzen

  for i:=0 to length(buch)-1 do SchreibBuch[i]:=Buch[i]; //Tiefenkopie
//...
                            for i:=0 to length(schreibBuch)-1 do
                                begin
                                     writestring(schreibbuch[i].Name);
                                     writestring(schreibbuch[i].Vorname);
Wozu kopierst du die Werte, hast du zuviel Speicher? :nixweiss: ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Bofrost_Mann Threadstarter
Hält's aus hier
Beiträge: 15

Win XP
Delphi 5, Delphi 2005
BeitragVerfasst: Do 07.02.08 15:06 
@narses: wie gesagt das Speichern und Lesen sollte nur rein funktionell einwandfrei arbeiten ... das Kopieren des Array-Records war auch nur mal für Testzwecke ... mittlerweile hab ich das Konzept in dem anderen Programm umgesetzt und dort gibts natürlich vorher keine Kopie des Arrays ...

LG Der Bofrost Mann