我正在使用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在这个问题中发布的函数:在Delphi 2009中将TMemoryStream转换为"字符串"
但我只是得到了字符串:"MZP
"
谁能帮我?
检查结果字符串的长度。我想该字符串包含所有二进制文件,但由于字符串正文中的零,您无法将其视为 ASCII 字符串。可执行文件的签名(第一个字节):4D 5A 90 00。ASCII 符号:MZP#0(P 在我的情况下是 ANSI 西里尔文,符号取决于代码页)。
我从以下方面使用: 在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');
不使用内存流作为中介。
all exe, dll file conatin an signature MZP#0 ...对于 pchar 字符串(delphi 中的大字符串),#0 表示字符串的结尾,调试检查器显示 MZP。
如果保留流的原始长度,则可以访问所有数据。
就像其他人建议的那样,在没有编码的情况下将二进制 DLL 转换为字符串是没有意义的。 但如果真的需要,你可以使用:TStringStream 类而不是 TMemoryStream。和 TStringStream.DataString 属性将获取字符串。再次请注意,直接将二进制数据转换为字符串可能会导致未指定的重用。使用编码模式:例如:base64,十六进制字符串
您可以使用 TStringList 类的 LoadFromStream 方法。
使用中间 TStrinStream 的方法很慢,因为它将内存从一个地方复制到另一个地方 2 次:
- 在调用 TStringStream.CopyFrom 方法时,
- 在最终分配结果 := 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);
//(...)
只是为了记录,在最近的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;