SunQuest
 
       Delphi-Kylix
  Home arrow Delphi-Kylix arrow Page 4 - Saving Images and Binary Files to a Databa...
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Dedicated Servers  
Actuate Whitepapers 
Moblin 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
DELPHI-KYLIX

Saving Images and Binary Files to a Database with Delphi 2
By: Danish Ahmed
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 3
    2007-07-03

    Table of Contents:
  • Saving Images and Binary Files to a Database with Delphi 2
  • Using Streams to save binaries
  • Retrieving BLOB data and saving to file
  • Checking the First 4 Bytes or Magic Numbers
  • Code

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT

    Stay one step ahead of the competition. Evaluate and give feedback on some of the hottest web development tools on the market today. Make your opinion heard! Click Here

    Saving Images and Binary Files to a Database with Delphi 2 - Checking the First 4 Bytes or Magic Numbers


    (Page 4 of 5 )

    In the above code we are saving the data to a file with the '.dat' extension. You could save it with a '.bmp' extension if you are sure that it is a bitmap. If you are not sure but save it as a bitmap when the actual data is of the JPEG type or any other type, the saved file will be of little or no use.

    I must confess that I was stuck at this juncture for some time. I was aware that files carry their signatures with them which can be extracted on the byte level. In fact Unix systems do not require extensions of a file name since they are handled according to the "magic number" found in the file's header. It is common knowledge that the first 16 bytes of a JPEG image contains information on the data it carries but I did not know the values for which I should be searching. Opening a few JPEG files in a Hex Editor I observed that the first 4 bytes of all of them were identical and and the values were  "FFD8 FFE0." A quick search on the web revealed that this was the magic number of the files with '.jpg' extensions. I tried opening different file formats in Hex Editor and looking for their magic numbers; almost all files of a similar type had the same exact first 4 bytes except bitmaps, which had only 2 identical bytes.

    Now that we know how to identify the file format from raw binary data, let us focus on how we can use the information to retrieve and save data to a file.  Earlier we used TFileStream to save the file to database but it cannot be used to retrieve data from the database since the constructor of TFileStream requires a file as parameter. Remember, each descendant of the TStream class can read and write only to a specific type of media. You can create an instance of a  TBlobStream or TADOBlobStream using the Blob field as the constructor parameter, and create an instance of a TFileStream and copy data from the BlobStream, or use TBlobField's "SaveToStream" method to save data to an instance of TMemoryStream. TMemoryStream can be used to store data in a dynamic memory buffer and provides file-like access capabilities. Furthermore, its constructor requires no parameters, which suits us fine at the moment.

    So let's get back to coding. I have already demonstrated how to connect to the database and retrieve one or more recordsets by executing a SQL statement through the command text property of the ADODataSet component. So the next step would be to  create an instance of TMemoryStream by calling its constructor. Since we are creating an object it will be necessary to put the code dealing with the object in guarded try/finally blocks so that the instance is freed even if an exception is raised in the try block. Read my previous article  Using Try and Finally to Help Prevent Memory Leaks During Dynamic Object Creation in Delphi to know why try/finally statements are important during object creation. After the TMemoryStream object has been created we would want to assign data to it by calling TBlobField's SaveToStream method while passing the Field name as the parameter.

       TblobField(ADODataSet1.FieldByName('Image')).SaveToStream(MStream);

    Now comes the interesting part which is comparing bytes to known magic numbers  of different file types. It would be a good idea to declare the variables as the WORD datatype just to make sure that exactly 2 bytes are copied from the stream. The Seek method moves the cursor to the specified position in the stream; in our case we would like to set the cursor at the beginning so it will be necessary to specify the origin offset of Seek method as "soFromBeginning."

    To read bytes from the stream to the variable, call the Read method with variable Sig1 as the buffer and Count as 2. The current position of the cursor should now be incremented by 2 but to make doubly sure I will set the cursor position to 2 and read the next 2 bytes into another WORD variable, Sig2.  You can put the code that checks for the magic number in a loop to recursively parse through all of the data, but every file I opened in Hex Editor had their magic number in the beginning so I am interested in reading the first four bytes only.

    Now Intel machines use a little Endian format to read bytes. What this actually means is that the bytes are read backward; FFD8 become D8FF. So we will convert our hex magic numbers to read backward and then compare them with the values of the variables. When a match is found you can save it to the file format it matches and then use ShellExecute to launch it with the associated application, or you can load it directly from stream to one of the components if it supports the format. For instance, if the data type is found to be of the bitmap type you can load it in the image component by calling the method

             Image1.Picture.Bitmap.LoadFromStream (MStream);

    Or you can create a JPEG object and copy the data from the stream and load it on Image component. In fact you can do a lot of things with it depending on your requirements.

    More Delphi-Kylix Articles
    More By Danish Ahmed


     

    DELPHI-KYLIX ARTICLES

    - Client Dataset: Working with Data Packets an...
    - Using the Client Dataset in an N-Tiered Appl...
    - Using the Client Dataset in Two-Tiered Clien...
    - Using the Client Dataset in File-Based Archi...
    - Demystifying the Client Dataset
    - Working with INI Files in Delphi
    - Creating Data Link (UDL) Files in Delphi
    - Looking at the Details for an Invoicing Appl...
    - Invoicing in Delphi: Show Me the Money
    - Saving Images and Binary Files to a Database...
    - Saving Files to a Database using Delphi: Sav...
    - Creating CF Applications and Integrating a S...
    - Using Try and Finally to Help Prevent Memory...
    - The Implementation of an FTP Server
    - FTP Server: The Theory







    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 4 hosted by Hostway