Writing strings to TMemoryStream

35,321

When you use

Stream.Write(Str[1], StrLen);

you're writing first StrLen bytes to the stream. But the (unicode)string data is actually StrLen * SizeOf(Char) bytes (you have to take the size of the char type into account). So following should work:

Stream.Write(Str[1], StrLen * SizeOf(Str[1]));

Same when reading data back from stream.

Share:
35,321
JakeSays
Author by

JakeSays

Updated on July 09, 2022

Comments

  • JakeSays
    JakeSays almost 2 years

    I have read alot of discussions on here regarding writing strings to a TMemoryStream and saving to file and reading the strings back in to TMemoryStream

    I dont know what I have done wrong here, but either my SaveData or my LoadData is wrong. I can check the value of Title before I call SaveData and it holds what I expect. However, when I call LoadData and check the value of Title, it is garbage. Can anyone tell me what I have done wrong please

    procedure SaveData(FileName: TFileName);
    var
     MemStr: TMemoryStream;
     Title: String;
    begin
     MemStr:= TMemoryStream.Create;
    try
     MemStr.Seek(0, soFromBeginning);
     WriteStreamStr( MemStr, TItle );
     MemStr.SaveToFile(FileName);
    finally
     MemStr.Free;
    end;
    end;
    
    procedure LoadData(FileName: TFileName);
    var
     MemStr: TMemoryStream;
     Title: String;
    begin
     MemStr:= TMemoryStream.Create;
     try
      MemStr.LoadFromFile(FileName);
      MemStr.Seek(0, soFromBeginning);
      Title := ReadStreamStr( MemStr );
     finally
       MemStr.Free;
      end;
    end;
    
    
    
    procedure WriteStreamInt(Stream : TStream; Num : integer);
     {writes an integer to the stream}
    begin
     Stream.WriteBuffer(Num, SizeOf(Integer));
    end;
    
    procedure WriteStreamStr(Stream : TStream; Str : string);
     {writes a string to the stream}
    var
     StrLen : integer;
    begin
     {get length of string}
     StrLen := Length(Str);
     {write length of string}
     WriteStreamInt(Stream, StrLen);
     if StrLen > 0 then
     {write characters}
     Stream.Write(Str[1], StrLen);
    end;
    
    
    function ReadStreamInt(Stream : TStream) : integer;
     {returns an integer from stream}
    begin
     Stream.ReadBuffer(Result, SizeOf(Integer));
    end;
    
    function ReadStreamStr(Stream : TStream) : string;
     {returns a string from the stream}
    var
     LenStr : integer;
    begin
     Result := '';
     {get length of string}
     LenStr := ReadStreamInt(Stream);
     {set string to get memory}
     SetLength(Result, LenStr);
     {read characters}
     Stream.Read(Result[1], LenStr);
    end;
    
  • David Heffernan
    David Heffernan about 11 years
    ByteLength(Str) exists for this