I am trying to read two strings of varying length from a TMemoryStream, but both streams end up being the same length. So if, for example, the first string is 'abcdefghijkl', and the second one is 'wxyz', the value I get for the second string is 'wxyzefghijkl' (the first four characters of my new string ('wxyz') followed by the remaining characters of the 1st string that have not been replaced by 'wxyz'
My code is:-
var
L : LongInt
S : string;
...
msRecInfo.Position := 0;
msRecInfo.Read(L, SizeOf(L)); // read size of following string ...
SubStream.Clear;
SubStream.CopyFrom(msRecInfo, L); // copy next block of data to a second TMemoryStream
if (L > 0) then S := StreamToString(SubStream); //convert the stream into a string
msRecInfo.Read(L, SizeOf(L)); // get size of following string ...
SubStream.CopyFrom(msRecInfo, L);
if (L > 0) then S := StreamToString(SubStream);
I have been battling with this for hours without success. Can anyone point out what I am doing wrong?
You are not calling
SubStream.Clear()before the 2nd call toSubStream.CopyFrom(). So, the 1st call toStreamToString(SubStream)leavesSubStream.Positionat the end of the stream, then the subsequentSubStream.CopyFrom()adds more data to the stream, preserving the existing data. Then the subsequentStreamToString(SubStream)reads all of the data fromSubStream.Also, be aware that if
Lis0when you pass it toSubStream.CopyFrom(), it will copy the entiremsRecInfostream. This is documented behavior:https://docwiki.embarcadero.com/Libraries/en/System.Classes.TStream.CopyFrom
So, you need to move up your
L > 0check, eg:I would suggest wrapping this logic into a reusable function, eg:
Although, if feasible, I would suggest just getting rid of
SubStreamaltogether, updateStreamToString()to takeLas an input parameter, so that you can read thestringfrommsRecInfodirectly, eg:No need for a 2nd
TMemoryStreamif you can avoid it.