Преобразование TMemoryStream в 'String' в Delphi 2009
У нас был следующий код до 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;
Как мы можем преобразовать этот код для поддержки Unicode сейчас с Delphi 2009?
Ответы
Ответ 1
Код, который у вас есть, излишне сложный, даже для старых версий Delphi. Почему необходимо вывести строку-версию потока, чтобы перераспределить память потока, в конце концов?
function MemoryStreamToString(M: TMemoryStream): string;
begin
SetString(Result, PChar(M.Memory), M.Size div SizeOf(Char));
end;
Это работает во всех версиях Delphi, а не только в Delphi 2009. Он работает, когда поток пуст без какого-либо особого случая. SetString
является недооцененной функцией.
Если содержимое вашего потока не переключается на Unicode с вашим коммутатором на Delphi 2009, вы должны использовать эту функцию вместо:
function MemoryStreamToString(M: TMemoryStream): AnsiString;
begin
SetString(Result, PAnsiChar(M.Memory), M.Size);
end;
Это эквивалентно исходному коду, но пропускает специальные случаи.
Ответ 2
Или, может быть, вы можете реорганизовать свой код, чтобы напрямую использовать TStringStream? Вы можете использовать его вместо TMemoryStream (они имеют один и тот же интерфейс), и вы можете "конвертировать" его в строку, просто вызывая myString: = myStringStream.DataString;
Ответ 3
"Чище" может быть:
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;
Ответ 4
Я использую:
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;
Он был протестирован только с Delphi XE7.
Ответ 5
Я еще не обновился, но я понимаю:
NewCapacity := (M.Size + 1) * SizeOf(Char);
Ответ 6
Существует фактор TStringStream
, который сможет вам помочь. , Вы можете загрузить содержимое другого потока следующим образом:
var StringStream: TStringStream;
begin StringStream := TStringStream.Create('');
StringStream.CopyFrom(OtherStream, OtherStream.Size);
end;
Теперь вы можете войти в серию для типа String, такого как это: свойство data-string включает серию... но не пытайтесь делать это с большими объектами, например, если вы загружаете огромный файл в некоторый файловый поток, затем копируете это к вашему собственному потоку строк и приложите усилия, чтобы произвести это, потому что это организует много памяти!
надеюсь, это поможет
Ответ 7
Вы можете привести его к правильному символьному указателю и просто назначить его:
procedure getMemoryStreamAsString( aMS_ : TMemoryStream );
var
ws : widestring; // in newer Delphi it can be string
ans : ansistring;
begin
ws := pwidechar( aMS_.memory );
// OR
ans := pansichar( aMS_.memory );
end;