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.
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.