在Delphi 2009中将TMemoryStream转换为'String'

时间:2009-04-09 03:24:23

标签: delphi string unicode delphi-2009 memorystream

我们在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;

现在如何使用Delphi 2009将此代码转换为支持Unicode?

7 个答案:

答案 0 :(得分:63)

即使对于较旧的Delphi版本,您拥有的代码也不必要地复杂。为什么要获取流的字符串版本会强制重新分配流的内存?

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

适用于所有Delphi版本,而不仅仅是Delphi 2009.它在流为空时没有任何特殊情况。 SetString是一个不被重视的功能。

如果您切换到Delphi 2009时流的内容没有更改为Unicode,那么您应该使用此功能:

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

这相当于原始代码,但会跳过特殊情况。

答案 1 :(得分:16)

或许您可以重构代码以直接使用TStringStream?您可以使用它而不是TMemoryStream(它们具有相同的接口),您只需调用myString:= myStringStream.DataString即可将其“转换”为字符串。

答案 2 :(得分:12)

“更清洁”的方式可能是:

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;

答案 3 :(得分: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进行了测试。

答案 4 :(得分:2)

我尚未升级,但我的理解是:

NewCapacity := (M.Size + 1) * SizeOf(Char);

答案 5 :(得分:2)

有一个称为TStringStream的因素可以为您提供帮助。 。您可以像这样加载另一个流的内容:

var StringStream: TStringStream; 
begin StringStream := TStringStream.Create(''); 
StringStream.CopyFrom(OtherStream, OtherStream.Size); 
end;

您现在可以进入类似String的系列了:data-string属性包含系列...但是不要对大型对象尝试这样做,例如在将大文件加载到某些对象的情况下filestream然后将其复制到您自己的stringstream中,并努力产生它,因为它会占用大量内存!

希望有帮助

答案 6 :(得分:1)

您可以将其转换为正确大小的字符指针,然后简单地将其分配:

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;