Converting TMemoryStream to 'String' in Delphi 2009
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);
dmillam
Updated on July 20, 2020Comments
-
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?