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

时间:2012-05-05 13:52:34

标签: string delphi memory stream

我正在使用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

任何人都可以帮助我吗?

6 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

我曾经从Converting TMemoryStream to 'String' in Delphi 2009使用以下功能:

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文件。我花了一个小时才找到这个解决方案。在Internet上找到的将内存流转换为字符串的所有功能都不适用于我。这是唯一有效的方法。正常的解决方案是:s:= {Http.Get('http://www.test.com/test.exe');而不使用内存流作为中介。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

  1. 使用TStringStream.CopyFrom方法,
  2. ,并在最终分配结果中:= 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);
    //(...)