Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi - MemoryStream or FileStream

I am downloading an EXE file from internet using Indy (idHTTP), and I can use memorystream or filestream to save it to disk, but I really do not know if there is any difference between them (maybe in the result structure of the file?). I could't find yet an answer for this.

Where, here are 2 simple functions to simulate what I am doing:

Function DownloadMS(FUrl, Dest: String): Boolean;
var
  Http: TIdHTTP;
  Strm: TMemoryStream;
Begin
  Result := False;
  Http := TIdHTTP.Create;
  Strm := TMemoryStream.Create;
  With Http, Strm Do
  Try
    Try
      Get(FUrl, Strm);
      If (Size > 0) Then
      Begin
        Position := 0;
        SaveToFile(Dest);
        Result := True;
      end;
    Except
    end;
  Finally
    Strm.Free;
    Http.Free;
  end;
end;

Function DownloadFS(FUrl, Dest: String): Boolean;
var
  Http: TIdHTTP;
  Strm: TFileStream;
Begin
  Result := False;
  Http := TIdHTTP.Create;
  Strm := TFileStream.Create(Dest, fmCreate);
  With Http, Strm Do
  Try
    Try
      Get(FUrl, Strm);
      Result := (Size > 0);
    Except
    end;
  Finally
    Strm.Free;
    Http.Free;
  end;
end;

What you experts think about using one or other type (memorystream or filestream)? Is there any difference in the structure of the EXE file when using one or other type? What type is recommended?

Thank you! Have a nice weekend!

like image 839
Guybrush Avatar asked May 04 '13 14:05

Guybrush


2 Answers

There is no difference between TMemoryStream or TFileStream from the stream point of view.

They are both streams and hold a stream of bytes and are both derived from TStream.

You can implement your function generalized like this

function DownloadToStream( const AUrl : String; ADest : TStream ): Boolean;
var
  LHttp: TIdHTTP;
begin
  LHttp := TIdHTTP.Create;
  try
    LHttp.Get( AUrl, ADest );
    Result := ADest.Size > 0;
  finally
    LHttp.Free;
  end;
end;

and call it with a TFileStream

var
  LStream : TStream;

begin
  LStream := TFileStream.Create( 'MyFile.exe', fmCreate );
  if DownloadToStream( '', LStream ) then
    ...
end;

or TMemoryStream or whatever stream instance you like

like image 101
Sir Rufo Avatar answered Sep 20 '22 15:09

Sir Rufo


In many cases there will be no point in putting an intermediate memory stream in between the download and the file. All that will do is consume memory because you have to put the entire file in memory before you can put it to disk. Using a file stream directly avoids that issue.

The main situation where the file stream option has problems is if you want to be sure that you've downloaded the entire file successfully before saving to disk. For example, if you are overwriting a previous version of a file, you may want to download it, check a hash signature, and only then overwrite the original file. In that scenario you need to put the file to some temporary location before over-writing. You could use a memory stream, or you could use a file stream using a temporary file name.

like image 43
David Heffernan Avatar answered Sep 22 '22 15:09

David Heffernan