33

在 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?

4

7 回答 7

72

您拥有的代码过于复杂,即使对于较旧的 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;

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

于 2009-04-09T08:30:31.750 回答
20

或者也许您可以重构您的代码以直接使用 TStringStream ?您可以使用它代替 TMemoryStream (它们具有相同的接口),您可以通过简单地调用 myString := myStringStream.DataString; 将其“转换”为字符串;

于 2009-04-09T05:51:17.717 回答
15

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

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;
于 2009-04-09T14:30:56.173 回答
6

我用:

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 上进行了测试。

于 2014-12-31T01:33:43.097 回答
2

我还没有升级,但我的理解是:

NewCapacity := (M.Size + 1) * SizeOf(Char);
于 2009-04-09T03:31:02.607 回答
2

有一个因素TStringStream可以帮助你。. .您可以像这样加载另一个流的内容:

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

您现在可以进入这样的字符串类型的系列:数据字符串属性包含系列......但不要尝试使用大型对象,例如在您将大文件加载到某个文件流然后复制的情况下这到你自己的字符串流并努力产生它,因为它安排了大量的内存!

希望有帮助

于 2018-10-10T10:44:26.177 回答
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;
于 2019-07-19T10:42:15.393 回答