Подтвердить что ты не робот

Преобразование 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?

4b9b3361

Ответ 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;