将“TMemoryStream”转换为“String”,反之亦然

问题描述 投票:0回答:7

我正在使用 IdHttp 从网络下载文件,如下所示:

var
 MS: TMemoryStream;

procedure Test1;
var
 Http: TIdHTTP;
begin
Http := TIdHTTP.Create(nil);
  try
    MS := TMemoryStream.Create;
    try
      Http.Get('http://www.test.com/test.exe', MS);
    finally
      MS.Free;
    end;
  finally
    Http.Free;
  end;
end;

因此,下载的文件/流(不知道如何发音)将位于

MS.Memory

嗯,我想获取或转换

MS.Memory
为字符串,反之亦然。

我已经尝试过 Rob Kennedy 在这个问题中发布的功能:Converting TMemoryStream to 'String' in Delphi 2009

但是我刚刚得到了字符串:“

MZP

有人可以帮助我吗?

string delphi memory stream
7个回答
4
投票

检查结果字符串的长度。我认为该字符串包含所有二进制文件,但由于字符串正文中的零,您无法将其视为 ASCII 字符串。 可执行文件的签名(第一个字节):4D 5A 90 00。ASCII 符号:MZP#0(在我的例子中,P 是 ANSI 西里尔字母,符号取决于代码页)。


2
投票

我使用了:在 Delphi 2009 中将 TMemoryStream 转换为“字符串”以下函数:

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;

Http.Get('http://www.test.com/test.exe', MS);
之后您可以使用:
s:=StreamToString(MS);

s 是字符串。 对我来说,它可以在 Delphi 10.2 上运行,用于从互联网上读取 pdf 文件。我花了一个小时才找到这个解决方案。在互联网上找到的所有将内存流转换为字符串的功能都不适合我。这是唯一有效的。 正常的解决方案是:s:=

Http.Get('http://www.test.com/test.exe');
,不使用内存流作为中介。


1
投票

所有 exe、dll 文件都包含签名 MZP#0 ... 对于 pchar 字符串(delphi 中的大字符串)#0 表示字符串结尾,调试检查器显示 MZP。

如果保留流的原始长度,您可以访问所有数据。


1
投票

就像其他人建议的那样,在不编码的情况下将二进制 dll 转换为字符串是没有意义的。但如果确实需要,您可以使用: TStringStream 类而不是 TMemoryStream。 和 TStringStream.DataString 属性将获取字符串。 请再次注意,直接将二进制数据转换为字符串可能会导致未指定的结果。使用编码模式:例如:base64、十六进制字符串


1
投票

使用中间 TStringStream 的方法很慢,因为它将内存从一个地方复制到另一个地方 2 次:

  1. 在调用 TStringStream.CopyFrom 方法时,
  2. 最后赋值 Result := TStringStream.DataString

我建议不使用中间对象,直接将内存复制 1 次到结果。这是我的功能:



    Function TryMemoryStreamToString(const MS: TMemoryStream; var s: string): Boolean;
      begin
        Result := False; if(MS=nil)then exit;
        try
          SetLength(s, MS.Size - MS.Position);
          MS.Read(s[1], Length(s));
          Result := True;
        except
          Result := False;
        end;
      end;

当然,您也可以直接将字符串作为结果返回:



    Function MemoryStreamToStringDef(const MS: TMemoryStream; const ADefault: string = ''): string;
      begin
        if Assigned(MS)
           then try
                  SetLength(Result, MS.Size - MS.Position);
                  MS.Read(Result[1], Length(Result));
                except
                  Result := ADefault;
                end
           else Result := ADefault;
      end;

请记住,从 MemoryStream 读取将从 TMemoryStream.Position 指向的位置开始。因此请注意这一点并确保它位于您想要的位置,例如,如果您始终想要整个内容,请在调用函数之前将其设置为流的开头:



    var
      MS : TMemorySTream;
      s  : string;
    
    //(...)
      MS.Position := 0; 
      s := MemoryStreamToStringDef(MS);
    //(...)


0
投票

您可以使用 TStringList 类的 LoadFromStream 方法。


0
投票

仅供记录,在最近的 Delphi 中,您可以使用 TStreamReader/TStreamWriter 从 TStream 后代读取/写入字符串,如下面的代码所示(其中 LoadFromString/SaveToString 是您自己的方法来对字符串执行某些操作)您从流中读取并分别从您的某个对象中获取字符串,以便将其写入流中):

procedure TStoryItem.LoadReadCom(const Stream: TStream);

begin
  var reader := TStreamReader.Create(Stream);
  LoadFromString(reader.ReadToEnd);
  FreeAndNil(reader); //the reader doesn't own the stream by default, so this won't close the stream
end;

procedure TStoryItem.SaveReadCom(const Stream: TStream);
begin
  var writer := TStreamWriter.Create(Stream);
  writer.Write(SaveToString);
  FreeAndNil(writer); //the writer doesn't own the stream by default, so this won't close the stream
end;
© www.soinside.com 2019 - 2024. All rights reserved.