String 将“转换为”;TMemoryStream“;至;“字符串”;反之亦然

String 将“转换为”;TMemoryStream“;至;“字符串”;反之亦然,string,delphi,memory,stream,String,Delphi,Memory,Stream,我正在使用IdHttp从web下载一个文件,如下所示: 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;

我正在使用IdHttp从web下载一个文件,如下所示:

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在这个问题中发布的函数:

但是我刚刚得到字符串:
MZP


有人能帮我吗?

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

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

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


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

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

我从以下函数使用:

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;
函数StreamToString(aStream:TStream):字符串;
变量
SS:TStringStream;
开始
如果为零,则
开始
SS:=TStringStream.Create(“”);
尝试
SS.CopyFrom(aStream,0);//不需要定位在0,也不需要提供大小
结果:=SS.DataString;
最后
SS.免费;
终止
结束其他
开始
结果:='';
终止
终止
Http.Get('http://www.test.com/test.exe",MS),您可以使用:
s:=StreamToString(MS)

s是字符串。
对我来说,它在Delphi10.2上工作,用于从internet读取pdf文件。我花了一个小时才找到这个解决办法。在互联网上找到的所有将记忆流转换成字符串的功能对我来说都不起作用。这是唯一有效的方法。通常的解决方案是:s:=
Http.Get('http://www.test.com/test.exe');不使用内存流作为中介。

使用中介流的方法速度较慢,因为它将内存从一个位置复制到另一个位置2次:

  • 在调用TStringStream.CopyFrom方法时
  • 在最终赋值结果处:=TStringStream.DataString
  • 我建议不要使用中间对象,直接将内存复制1次到结果中。以下是我的功能:

    
    函数TryMemoryStreamToString(常量MS:TMemoryStream;变量s:string):布尔值;
    开始
    结果:=假;如果(MS=nil),则退出;
    尝试
    设定长度(s,MS.尺寸-MS.位置);
    MS.Read(s[1],长度(s));
    结果:=真;
    除了
    结果:=假;
    终止
    终止
    
    当然,您也可以直接返回字符串作为结果:

    
    函数MemoryStreamToStringDef(const-MS:TMemoryStream;const-ADefault:string=''):string;
    开始
    如果分配(毫秒)
    然后试试看
    设置长度(结果,毫秒大小-毫秒位置);
    MS.Read(结果[1],长度(结果));
    除了
    结果:=ADefault;
    终止
    否则结果:=ADEFULT;
    终止
    
    只要记住,从MemoryStream的读取将从TMemoryStream.Position指向的任何位置开始。因此,请注意这一点,并确保它位于您想要的位置,例如,如果您一直想要整个内容,请在调用函数之前将其设置为流的开头:

    
    变量
    MS:TMemorySTream;
    s:字符串;
    //(...)
    女士职位:=0;
    s:=内存流到字符串的长度(MS);
    //(...)
    
    为什么需要将
    二进制数据转换为字符串?这与您的代码目的没有任何意义。@kobik,我的程序在内存中加载了一个dll,我的“竞争对手”现在无法获得。不幸的是,有人获得了。。。因此,我想将dll写入一个字符串中,该字符串可以转换为MemoryStream并加载。@TLama,如果我使用具有字符串结果的
    Get
    函数,将与MS.Memory中包含的数据相同?仍在尝试破解世界?;)DLL不是字符串。你到底想干什么?你认为你的竞争对手真的会发现很难实现HTTP GET吗?