Using an instance of TMemoryStream as an intermediate storage is a common approach. But it is not safe to use a memory stream when the content is too large, otherwise the application may run out of memory and crash.

The only safe approach for handling an intermediate storage, is to use a temporary file. Of course, using a temporary file is not as easy as using a memory stream. Because, we need to write code to get a unique file name, create the file and finally delete it when it is no more needed.

Here, I am going to introduce you a stream class named TTemporaryFileStream. This class takes care of creating and deleting the temporary file and we can use it as easy as a memory stream.

type
  TTemporaryFileStream = class(THandleStream)
  public
    constructor Create;
    destructor Destroy; override;
  end;
 
constructor TTemporaryFileStream.Create;
var
  TempPath: array[0..MAX_PATH] of AnsiChar;
  TempFile: array[0..MAX_PATH] of AnsiChar;
  TempHandle: THandle;
begin
  GetTempPathA(High(TempPath), TempPath);
  GetTempFileNameA(TempPath, 'DA', 0, TempFile);
  TempHandle := CreateFileA(TempFile, GENERIC_READ or GENERIC_WRITE, 0, nil,
    CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_RANDOM_ACCESS or
    FILE_FLAG_DELETE_ON_CLOSE, 0);
  Assert(TempHandle <> INVALID_HANDLE_VALUE, 'Unable to create temporary file');
  inherited Create(TempHandle);
end;
 
destructor TTemporaryFileStream.Destroy;
begin
  FileClose(Handle);
  inherited Destroy;
end;

UPDATE: Added the missing destructor!

Reader's Comments »

  1. 1. By me on November 6, 2010 at 19:21

    Kambiz, can you please provide an example how to use this?

  2. 2. By Kambiz on November 6, 2010 at 20:54

    Sure, it is a pleasure!

    Suppose we want to get favicon of a website, and display it on an instance of TImage control.

    var
      Temp: TTemporaryFileStream;
    begin
      Temp := TTemporaryFileStream.Create;
      try
        IdHTTP1.Get('http://www.delphiarea.com/favicon.ico', Temp);
        Temp.Position := 0;
        Image1.Picture.Icon.LoadFromStream(Temp);
      finally
        Temp.Free;
      end;
    end;

    I hope this example could be helpful.

  3. 3. By me on November 7, 2010 at 20:29

    Thanks a lot! I thought it would be much more complicated than simply reading and freeing the stream.

  4. 4. By Mostafa Sarbazzadeh on August 27, 2011 at 10:14

    it’s usefull

  5. 5. By gode on December 13, 2012 at 13:50

    Hi.
    I need to read data from a large file (2-3GB) in a 32bit app and show the data on screen. So, obviously, I cannot load the entire file in RAM. Will TTemporaryFileStream approach work?

  6. 6. By Kambiz on December 14, 2012 at 11:12

    Gode, you do not need a temporary stream for your purpose. A usual file stream does the job for you.