Saxon
asked on
read from TMemoryStream fails
I want to use a stream for example for clipboard operations. If I read and write the stream within the same procedure (Button3Click) it occures successfull. If I split this procedure into the Button1Click+Button2Click procedures I loose in the line marked as {B} the value of RecordDestination.Wort. This value has been modified in a mysterious way at this point.
Up to now I have no expirience using streams. May be I'm wrong but I think it should be possible to to use streams in this way.
type
TMyRecord = record
Zahl: cardinal;
Wort: String;
end;
var
Form1: TForm1;
MyStream: TMemoryStream;
implementation
procedure TForm1.Button1Click(Sender : TObject);
var
RecordSource: TMyRecord;
begin
RecordSource.Zahl:=123;
RecordSource.Wort:='BullSh it';
MyStream:=TMemoryStream.Cr eate;
MyStream.Clear;
MyStream.Write(RecordSourc e,SizeOf(R ecordSourc e));
end;
procedure TForm1.Button2Click(Sender : TObject);
var
RecordDestination: TMyRecord;
begin
MyStream.Seek(0,soFromBegi nning);
MyStream.Read(RecordDestin ation,MySt ream.Size) ;
MyStream.Free;
{A} Edit5.Text:=IntToStr(Recor dDestinati on.Zahl);
Edit6.Text:=RecordDestinat ion.Wort;
end;
procedure TForm1.Button3Click(Sender : TObject);
var
RecordSource, RecordDestination: TMyRecord;
begin
RecordSource.Zahl:=124;
RecordSource.Wort:='Bulley e';
MyStream:=TMemoryStream.Cr eate;
MyStream.Clear;
MyStream.Write(RecordSourc e,SizeOf(R ecordSourc e));
MyStream.Seek(0,soFromBegi nning);
MyStream.Read(RecordDestin ation,MySt ream.Size) ;
MyStream.Free;
{B} Edit5.Text:=IntToStr(Recor dDestinati on.Zahl);
Edit6.Text:=RecordDestinat ion.Wort;
end;
Up to now I have no expirience using streams. May be I'm wrong but I think it should be possible to to use streams in this way.
type
TMyRecord = record
Zahl: cardinal;
Wort: String;
end;
var
Form1: TForm1;
MyStream: TMemoryStream;
implementation
procedure TForm1.Button1Click(Sender
var
RecordSource: TMyRecord;
begin
RecordSource.Zahl:=123;
RecordSource.Wort:='BullSh
MyStream:=TMemoryStream.Cr
MyStream.Clear;
MyStream.Write(RecordSourc
end;
procedure TForm1.Button2Click(Sender
var
RecordDestination: TMyRecord;
begin
MyStream.Seek(0,soFromBegi
MyStream.Read(RecordDestin
MyStream.Free;
{A} Edit5.Text:=IntToStr(Recor
Edit6.Text:=RecordDestinat
end;
procedure TForm1.Button3Click(Sender
var
RecordSource, RecordDestination: TMyRecord;
begin
RecordSource.Zahl:=124;
RecordSource.Wort:='Bulley
MyStream:=TMemoryStream.Cr
MyStream.Clear;
MyStream.Write(RecordSourc
MyStream.Seek(0,soFromBegi
MyStream.Read(RecordDestin
MyStream.Free;
{B} Edit5.Text:=IntToStr(Recor
Edit6.Text:=RecordDestinat
end;
Saxon,
igor is right.
the type "string" is kind of (not exactly) a pointer to an array of char. That means your record is only 8 bytes long. If you use igor's variant then your record will be 4+256 bytes long, since the characters of your string are then really stored in your record.
If 256 bytes are not enough for you respectively if you want dynamic string because of some other reasons you can save your use the following code:
procedure TForm1.Button1Click(Sender : TObject);
var RecordSource : TMyRecord;
i1 : integer;
begin
RecordSource.Zahl:=123; RecordSource.Wort:='BullSh it';
MyStream:=TMemoryStream.Cr eate; // you don't need to clear it...
try
// writing:
MyStream.Write(RecordSourc e.Zahl,siz eOf(cardin al));
i1:=length(RecordSource.Wo rt);
MyStream.Write(i1,sizeOf(i nteger));
MyStream.Write(PChar(Recor dSource.Wo rt)^,i1);
// reading:
MyStream.position:=0;
MyStream.Read(RecordSource .Zahl,size Of(cardina l));
MyStream.Read(i1,sizeOf(in teger));
SetLength(RecordSource.Wor t,i1);
MyStream.Read(PChar(Record Source.Wor t)^,i1);
finally MyStream.Free end;
end;
Regards, Madshi.
P.S: Schöne Grüße...
igor is right.
the type "string" is kind of (not exactly) a pointer to an array of char. That means your record is only 8 bytes long. If you use igor's variant then your record will be 4+256 bytes long, since the characters of your string are then really stored in your record.
If 256 bytes are not enough for you respectively if you want dynamic string because of some other reasons you can save your use the following code:
procedure TForm1.Button1Click(Sender
var RecordSource : TMyRecord;
i1 : integer;
begin
RecordSource.Zahl:=123; RecordSource.Wort:='BullSh
MyStream:=TMemoryStream.Cr
try
// writing:
MyStream.Write(RecordSourc
i1:=length(RecordSource.Wo
MyStream.Write(i1,sizeOf(i
MyStream.Write(PChar(Recor
// reading:
MyStream.position:=0;
MyStream.Read(RecordSource
MyStream.Read(i1,sizeOf(in
SetLength(RecordSource.Wor
MyStream.Read(PChar(Record
finally MyStream.Free end;
end;
Regards, Madshi.
P.S: Schöne Grüße...
ASKER
Great, it works, but please explain me at last, why it works in the other case (and sometime - I tried different other versions - in the splitted manner too).
Because you saved the pointer to the string and reloaded it. So if the record (and the string) still exists the loaded pointer is still correct.
Which way do you want to use? Igor's or mine?
Which way do you want to use? Igor's or mine?
ASKER
Thx, for your string->widestring->string hint too!
For the moment I'll use Igor's way, but the points I'd like to give to you. Your answer was more helpful for my understanding. Hope Igor agrees, thanks to you too!
Lutz
For the moment I'll use Igor's way, but the points I'd like to give to you. Your answer was more helpful for my understanding. Hope Igor agrees, thanks to you too!
Lutz
Sure man,
please answer Madshi,
igor
please answer Madshi,
igor
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
nothing specific friend, is just a SHIFT saving...
regards, igor (or may be I am a poet like Cummings)
regards, igor (or may be I am a poet like Cummings)
Igor,
ok, you can call me "madshi" to save another shift... :-)
Regards, Madshi.
ok, you can call me "madshi" to save another shift... :-)
Regards, Madshi.
nothing specific friend, is just a SHIFT saving...
regards, igor (or may be I am a poet like Cummings)
regards, igor (or may be I am a poet like Cummings)
ok madshi ;-) sorry for reposting...
you can not simply read and write the records containing pointers or dynamic strings:
instead you may change the record in to
TMyRecord = record
Zahl: cardinal;
Wort: ShortString;
end;
and try again,
regards, igor