Converting TMemoryStream to 'String' in Delphi 2009

79,231

Solution 1

The code you have is unnecessarily complex, even for older Delphi versions. Why should fetching the string version of a stream force the stream's memory to be reallocated, after all?

function MemoryStreamToString(M: TMemoryStream): string;
begin
  SetString(Result, PChar(M.Memory), M.Size div SizeOf(Char));
end;

That works in all Delphi versions, not just Delphi 2009. It works when the stream is empty without any special case. SetString is an under-appreciated function.

If the contents of your stream aren't changing to Unicode with your switch to Delphi 2009, then you should use this function instead:

function MemoryStreamToString(M: TMemoryStream): AnsiString;
begin
  SetString(Result, PAnsiChar(M.Memory), M.Size);
end;

That's equivalent to your original code, but skips the special cases.

Solution 2

Or perhaps you can refactor your code to use directly a TStringStream directly? You can use it instead of TMemoryStream (they have the same interface) and you can 'convert' it to a string by simply calling myString := myStringStream.DataString;

Solution 3

A "cleaner" way might be:

function StreamToString(aStream: TStream): string;
var
  SS: TStringStream;
begin
  if aStream <> nil then
  begin
    SS := TStringStream.Create('');
    try
      SS.CopyFrom(aStream, 0);  // No need to position at 0 nor provide size
      Result := SS.DataString;
    finally
      SS.Free;
    end;
  end else
  begin
    Result := '';
  end;
end;

Solution 4

I use:

function StreamToString(const Stream: TStream; const Encoding: TEncoding): string;
var
  StringBytes: TBytes;
begin
  Stream.Position := 0;
  SetLength(StringBytes, Stream.Size);
  Stream.ReadBuffer(StringBytes, Stream.Size);
  Result := Encoding.GetString(StringBytes);
end;

It has been tested with Delphi XE7 only.

Solution 5

I have not upgraded yet, but my understanding is:

NewCapacity := (M.Size + 1) * SizeOf(Char);
Share:
79,231
dmillam
Author by

dmillam

Updated on July 20, 2020

Comments

  • dmillam
    dmillam almost 4 years

    We had the following code prior to Delphi 2009:

    function MemoryStreamToString(M : TMemoryStream): String;
    var
        NewCapacity: Longint;
    begin
        if (M.Size = > 0) or (M.Memory = nil) then
           Result:= '' 
        else
        begin
           if TMemoryStreamProtected(M).Capacity = M.Size then
           begin
               NewCapacity:= M.Size+1;
               TMemoryStreamProtected(M).Realloc(NewCapacity);
           end;
           NullString(M.Memory^)[M.Size]:= #0;
           Result:= StrPas(M.Memory);
        end;
    end;
    

    How might we convert this code to support Unicode now with Delphi 2009?