Useful delphi TStream descendants

Delphi has a number of very useful stream classes.

They all derive from TStream.

The basic version is TFileStream – this writes to a filesystem.

There is also THandleStream – this writes to a windows handle – useful if you need to keep a file locked then write to it.

TStringStream is useful when dealing with delphi strings – especially when writing to another stream.

TBlobStream is used for accessing blob data from a database.

TResourceStream is used to read from embedded resources.

TMemoryStream that acts upon blocks of memory. 

There are also the adapter streams that takes another stream as a parameter.

 There is the TIStream that acts as a bridge between TStreams and the IStreams interface.

These include ZipStreams, EncryptionStreams, SocketStreams &c

These all take the approach that everything looks like a file this massively simplifys code.

 

Storing jpegs in databases

I know that storing images in a database is oftern a bad idea.
However there can come requirements that force things on you.

For the database end I have used an IMAGE datatype in SQL Server.

The delphi approach is as follows:

You need to use GraphicEx to allow display in the normal controls.
All this requires is adding the GraphicEx unit to the end of your uses clause.

procedure LoadJPEGImageFromStream(const aImage: TImage;
  const stream: TStream);
var
  aJPEG : TJpegImage;
begin
    aJPEG := TJPEGImage.Create;
    try
      aJPEG.LoadFromStream(stream);
      aImage.Picture.Assign(aJPEG);
    finally
      aJPEG.Free;
    end;
end;

 

procedure LoadFromDB(Image : TImage; aField : TBlobField)
var
  aBLOBStream : TStream;
begin
  ado.Open;
  ado.First;

  aBLOBStream := adoFAX.CreateBlobStream(aField,bmRead);
  try
    LoadJPEGImageFromStream(Image, aBLOBStream );
  finally
    aBLOBStream.free;
  end;

end;
 

procedure SaveToDB(const filename : string)
var
  FS : TFileStream;
begin
  FS := TFileStream.Create(filename, fmOpenRead);
  try
    ado.open;
    ado.Insert;
    adoIMAGE.LoadFromStream(FS);
    ado.Post;
  finally
    FS.Free;
  end;
end;
 

Just to check that this is not a Delphi-only format I wrote the following test from C#:

            sqlDataAdapter1.Fill(dataSet11, “DB”);
            // How to get an image from a database in .NET                   
            pictureBox1.Image = new Bitmap( new MemoryStream( dataSet11.DB[0].IMAGE ) );
            pictureBox1.Height = pictureBox1.Image.Height;
            pictureBox1.Width = pictureBox1.Image.Width;
 

This loads the image previously stored by a Delphi app.

This ensures that the image format used is language neutral. 

Delphi 2006 Rocks!

The latest incarnation of Delphi (the tenth version) 2006 seems to be way beyond the microsoft contribution to the field. Out of the box it provides a massive component suite and extensive refactoring tools.

 

I have just upgraded a large Delphi 5 application suite to D2006 with very little pain.

A few objects had moved units, I had to add the variants unit in a lot of places. Some of the MIDAS parameters now expect TCustomClientDataSet rather than TClientDataset.

 It is impressive in that I was able to interchange COM clients and servers build with the differing versions without much trouble. In fact the code areas which we had used the built in events the least required fewer or no changes.

 A minor annoyance is that the TChart was missing from the QuickReports 4 suite.

TeeChart is an amazing chart control suite.

Delphi After Borland

Borland recently announced that they are selling their suite of developer tools and wish to focus on their application lifecycle tools.

As a long time Delphi developer this could be a good thing. Borland had not been paying these tools enough attention of late. Plus given Borland’s recent habit of changing names (Borland -> Inprise -> Borland.com -> Borland) they may even end up reacquiring the product line!

Borland have stated that they will only sell them to a company that would actively develop the products so they will not be mothballed.