September 1998
by Jim Bailey

 

How can I use BLOBs with C++Builder?

Binary Large Objects, or BLOBs, get considerable attention in Borland's newsgroups. Much of this notice is negative, but BLOBs are more reliable than ever in C++Builder 3.0. Essentially, a BLOB can store any data, regardless of its format or size. This is one of the few times you'll experience no bounds or rules in a development environment. Graphical objects, FAX files, and formatted or plain text memos are just a few of the uses for BLOB fields. In this article, we'll discuss some of the BLOB-related differences between C++Builder 1.0 and 3.0. We'll demonstrate how to use BLOBs in an application to create and store formatted memos as well as the contents of a file. And, we'll describe the methods to retrieve, store, and access information in BLOB fields.

 

About the sample application

You can download our sample application from www.cobb.com/cpb. We developed this application using C++Builder 3.0 and Interbase 4.2; the download ZIP file includes a script file that creates the Interbase GDB file. Many environments lack the ability to create formatted memos in a database. For instance, the standard TDBMemo component doesn't allow formatting--this frustrates users who want to format memo documents. We addressed this need by using Borland's RichEdit example application as the foundation of our sample application. It's a reasonably powerful example that uses TRichEdit to provide a broad range of formatting features. Figure A shows the application's visible components. (Borland included a data-aware TDBRichEdit component in C++Builder 3.0; however, we chose not to use it because the purpose of this article is to demonstrate BLOB methods for accessing and exchanging data.)

Figure A: Our sample application uses these visible components.
[ Figure A ]

 

BLOB objects

There are three fundamental BLOB objects: TBlobField and its descendents, TmemoField, and TGraphicField. According to the documentation What is this referring to? , the only difference in these field types from C++Builder 1.0 to 3.0 lies in the DataType property. Borland cleverly specifies the possible DataType settings as ftBlob, ftMemo, and ftGraphic.

Accessing BLOB data

You can access data in a BLOB field three ways: the Value property, SaveToStream/LoadFromStream, and SaveToFile/ LoadFromFile. The code in Listings A and B demonstrates these techniques by exchanging data between a BLOB field and a TRichEdit component. Listing A puts data into a BLOB field; this code is called when the memo text is modified to write changes back into the database. On the other hand, the code in >Listing B gets data out of a BLOB field. This code is called each time the current record changes to retrieve BLOB contents into the TRichEdit object.

Listing A: Inserting data into a BLOB field

case USE_VALUE:
  qBlobTestBLOB1->Value = 
	RichEdit1->Text;
  break;

case USE_STREAM:
  TBlobStream* theBStream;
  theBStream = new TBlobStream
	(BlobField, 
    		bmWrite);
  RichEdit1->Lines->SaveToStream
	(theBStream);
  delete theBStream;
  break;

case USE_FILE:
  //Save formatted file.
  RichEdit1->Lines->SaveToFile
	(TEMP_FILE_NAME); 

  //Load formatted file into Blob.
  BlobField->LoadFromFile(
	TEMP_FILE_NAME);      
  break;


Listing B: Getting data from a BLOB field

case USE_VALUE:
  RichEdit1->Text = 
	qBlobTestBLOB1->Value;
  break;

case USE_STREAM:
  TBlobStream* theBStream;
  theBStream = new TBlobStream
	(BlobField, 
    bmRead);
  RichEdit1->Lines->
	LoadFromStream
	(theBStream);
  delete theBStream;
  break;

case USE_FILE:
//Save formatted file into Blob.
  BlobField->SaveToFile
	(TEMP_FILE_NAME); 

//Load formatted file.
  RichEdit1->Lines->
	LoadFromFile(
    TEMP_FILE_NAME); 
  break;

The Value property is always available, of course, but it brings in RTF formatting as text. That defeats the purpose, since our target is formatted memos. To preserve formatting, use the TBlobStream VCL object, which offers several powerful methods for handling BLOB data.

 

Storing database data in a BLOB field

That brings us to the second objective of the sample application: storing the contents of any database file in a BLOB field. For example, you may need to archive all related files for a particular project. You can include any file type--drawing files, document files, spreadsheets, faxes, and more. The BlobType field, shown in the grid in Figure A, isn't related to the VCL property of the same name. If BlobType (the field) is set to .txt or .rtf, the BLOB's contents are displayed in the TRichEdit object. Otherwise, the BLOB field's contents are ignored. However, you can transfer the contents to a file by clicking the disk icon or choosing the File | SaveAs menu item.

In the sample application, we saved an Excel spreadsheet file in the database. Naturally, you must be able to retrieve all data from the database in its original format. Doing so is a little tricky because it requires some BLOB field configuration. The configuration is even more important in the sample application, because the same table stores files and memos.

Listing C shows some options for setting up a BLOB field for a data transfer. The Transliterate is crucial. If Transliterate is set true, it mangles binary data like that in an Excel, Word, or fax file--the data then can't be retrieved from the BLOB field for use by the originating application. This result is totally unacceptable, of course. However, setting Transliteration to false allows you to transfer a BLOB's contents with absolute accuracy.

Listing C: Configuring a BLOB field to transfer data

case RTF_BLOB
  BlobField->Transliterate = true;
  BlobField->SetFieldType(ftMemo);
  RichEdit1->PlainText = false;
  break;

case TXT_BLOB)
  BlobField->Transliterate = true;
  BlobField->SetFieldType(ftMemo);
  RichEdit1->PlainText = true;
  break;

default:
  BlobField->Transliterate = false;
  BlobField->SetFieldType(ftBlob);
  break;

Other functionality

In the sample application, the file functions (Open, Save, and so on) operate on the BLOB field. For example, the Open command opens a file and copies its contents to a BLOB field, while the Save command retrieves data from the BLOB field and copies it to a file. The sample application also presents an excellent paradigm for file archival and the creation of formatted memos. BLOBs provide an excellent tool for storing data when its size and type are unpredictable. The properties and methods provided in the VCL protect developers from the nitpicking details of moving data between files, visual text components, and databases.

I'd like to extend special thanks to Borland TeamB members Ralph Friedman and Scott Samet for their assistance in developing this topic.