Autor Beitrag
Tigerandy
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Mi 14.12.05 10:37 
Hallo,

wer kann mir sagen, warum folgender Code eine Zugriffsverletzung erzeugt? Unter der Vorraussetzung natürlich, dass das RichEdit1 existiert.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.FormActivate(Sender: TObject);
var kon: TStringStream;
begin
  kon.writestring('Test');
  RichEdit1.Lines.LoadFromStream(kon);
end;


Gruß
Tiger
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mi 14.12.05 10:50 
Du musst den TStringStream vorher erzeugen und natürlich auch freigeben, wenn du ihn nicht mehr brauchst. So ist es richtig:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TForm1.FormActivate(Sender: TObject);  
var kon: TStringStream;  
begin  
  kon := TStringStream.Create('');
  try
    kon.writestring('Test');  
    kon.Position := 0;
    RichEdit1.Lines.LoadFromStream(kon);  
  finally
    kon.Free;
  end;
end;


Nachdem du in den Stream geschrieben hast, musst du auch die aktuelle Position wieder an den Anfang des Streams setzen, bevor du den Inhalt auslesen kannst.

Stefan

_________________
Ein Computer ohne Windows ist wie eine Schokoladentorte ohne Senf.
Tigerandy Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Mi 14.12.05 11:23 
Danke für den Tip, dann liegt mein Problem wohl etwas tiefer begraben. Ich habe mir mit

ausblenden Delphi-Quelltext
1:
TFirma = record					


einen Datentyp deklariert der unter anderen Variablen auch

ausblenden Delphi-Quelltext
1:
kon: array[0..9of TStringStream;					


enthält. In diesem Array sollen die Inhalte von 10 Richedit-Feldern gespeichert und auch wieder ausgelesen werden können. Jetzt speichere ich diesen Record "TFirma" komplett in einer Datei und lese diese beim Programmstart auch wieder ein, d.h. nach dem Einlesen müsste der StringStream doch schon erzeugt sein. Erzeuge ich einen neuen mit einer anderen Variable (s) und weise dieser dann den Wert z.B.

ausblenden Delphi-Quelltext
1:
2:
s:=TStringStream.Create(''); 
s:=kon[0];


zu, so entsteht wieder eine Zugriffsverletzung beim Ausführen der Zeile:

ausblenden Delphi-Quelltext
1:
RichEdit.Lines.LoadFromStream(s);					


Wo liegt da mein Denkfehler, bzw. wie könnte ich das mit dem Speichern der 10 Richedit-Felder sonst lösen, da ja alles komplett in eine Datei soll...?
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mi 14.12.05 11:54 
user profile iconTigerandy hat folgendes geschrieben:
Danke für den Tip, dann liegt mein Problem wohl etwas tiefer begraben. Ich habe mir mit

ausblenden Delphi-Quelltext
1:
TFirma = record					


einen Datentyp deklariert der unter anderen Variablen auch

ausblenden Delphi-Quelltext
1:
kon: array[0..9of TStringStream;					


enthält. In diesem Array sollen die Inhalte von 10 Richedit-Feldern gespeichert und auch wieder ausgelesen werden können. Jetzt speichere ich diesen Record "TFirma" komplett in einer Datei und lese diese beim Programmstart auch wieder ein, d.h. nach dem Einlesen müsste der StringStream doch schon erzeugt sein.


Wenn ich dich richtig verstanden habe, hast du da einen grundsätzlichen Denkfehler. Ein Array von Objekten (ob nun TStringStream oder irgendwas anderes) enthält lediglich Referenzen (also Zeiger) auf die Objekte. Das in eine Datei zu speichern, bringt dir gar nichts, weil die Objekte selbst damit nicht gespeichert werden - nur die Adressen, wo diese Objekte im Arbeitsspeicher liegen. Beim nächsten Lauf des Programms sind die Adressen ungültig und ein Zugriff darauf führt nur zu einer Zugriffsverletzung. Du musst den Inhalt der TStringStreams speichern und wieder laden.

Stefan

_________________
Ein Computer ohne Windows ist wie eine Schokoladentorte ohne Senf.
Tigerandy Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Mi 14.12.05 12:06 
Ok, so ähnlich hatte ich mir das auch schon gedacht. Mit welchem Datentyp speichere ich die Inhalte am besten? Einen String dynamischer Länge lässt Delphi in einem Record scheinbar nicht zu. Was ist die beste Lösung? Z.B. Array[0..20000] of Char, da String[20000] nicht funktioniert? Und wenn ja, wie bekomme ich den Inhalt der StringStreams in dieses Array? Die Funktionen ReadString bzw. WriteString gibt es ja, aber für Arrays of Char wird das nicht funktionieren nehme ich an.
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mi 14.12.05 12:20 
Wenn du mit 255 Zeichen nicht auskommst, würde ich ein Dateiformat mit variabler Record-Grösse benutzen. Ein array[0..20000of Char würde zwar gehen, ist aber sehr ineffizient, da ja wahrscheinlich die meisten Einträge wesentlich kürzer sind. Dein Record kann dann statt StringStreams normale Strings verwenden, Lesen und Schreiben der Dateien mit TFileStreams.

Beim Schreiben eines Strings in einen TFileStream musst du dann erst die Länge schreiben, dann den String selbst:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
var
  s: String;
{...}
fileStream.Write(Length(s), sizeof(Integer));
fileStream.Write(PChar(s)^, Length(s));


Zum Lesen dann entsprechend zuerst die String-Länge lesen, dann den String auf die richtige Länge dimensionieren und dann einlesen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
  s: String;
  len : Integer;
{...}
fileStream.Read(len, sizeof(Integer));
SetLength(s, len);
fileStream.Read(PChar(s)^, len);


Stefan

_________________
Ein Computer ohne Windows ist wie eine Schokoladentorte ohne Senf.