string 在 Delphi 2009 中将 TMemoryStream 转换为“字符串”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/732666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 00:25:12  来源:igfitidea点击:

Converting TMemoryStream to 'String' in Delphi 2009

delphistringunicodedelphi-2009memorystream

提问by dmillam

We had the following code prior to 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;

How might we convert this code to support Unicode now with Delphi 2009?

我们现在如何使用 Delphi 2009 转换此代码以支持 Unicode?

回答by Rob Kennedy

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?

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

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. SetStringis an under-appreciated function.

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

If the contents of your stream aren't changing to Unicode with your switch to Delphi 2009, then you should use this function instead:

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

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.

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

回答by John Thomas

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;

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

回答by Nick Hodges

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;

回答by Ivelin Nikolaev

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.

它仅在 Delphi XE7 上进行了测试。

回答by Techpromint

There's a factor called TStringStreamthat will be able to assist you. . .you can load the contents of another flow like that:

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

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

You can now get into the series for a String kind such as this: The data-string property comprises the series... but do not try so with large objects such as in the event that you load a huge file to some filestream then copy this to your own stringstream and make an effort to produce it cause it arranges a lot of memory!

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

Hope that helps

希望有帮助

回答by Loren Pechtel

I have not upgraded yet, but my understanding is:

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

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

回答by The Bitman

You can cast it into the right sized character pointer and just simple assign it:

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

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;