BLOB (declare a variable-length field)

Top  Previous  Next

 

label

BLOB [,BINARY] [,NAME( )]

Label

The label of the BLOB (PROP:Label).

BLOB

Declares a variable-length string stored on disk per record which may be greater than 64K

BINARY

Declares the BLOB a storage area for binary data (PROP:BINARY).

NAME

Specifies the disk filename for the BLOB field (PROP:NAME).

BLOB (Binary Large OBject) declares a string field which is completely variable-length and may be greater than 64K in size. A BLOB must be declared before the RECORD structure. Generally, up to 255 BLOB fields may be declared in a FILE structure (the exact number and their manner of storage on disk is file driver dependent).

A BLOB may not be used as a variable--you may not name a BLOB as a control's USE attribute, or directly assign data to or from the BLOB.

You can use PROP:Handle to get the Windows handle to the BLOB entity and assign one BLOB to another: get the handle of both BLOB entities and then assign one BLOB's handle to the other BLOB's handle. A BLOB may not be accessed "as a whole;" you must either use Clarion's string slicing syntax to access the data (unlimited in 32-bit), or PROP:ImageBlob. The individual bytes of data in the BLOB are numbered starting with zero (0), not one (1). PROP:Handle when used with BLOB returns a Windows Global Memory Object Handle for use with low-level Windows GlobalXxxx() API calls that require it.

The SIZE procedure returns the number of bytes contained in the BLOB field for the current record in memory. You can also get (and set) the size of a BLOB using PROP:Size. You may set the size of the BLOB before assigning data to a new BLOB using string slicing, but it is not necessary as the size is automatically set by the string slice operation. You can also use PROP:ImageBlob to store and retrieve graphic images without first setting PROP:Size. It is a good idea to first set PROP:Size to zero (0) before assigning data to a BLOB that has not previously contained data, to eliminate any "junk" leftover from any previously accessed BLOB. When assigning from one BLOB to another using PROP:Handle, you may need to use PROP:Size to adjust the size of the destination BLOB to the size of the source BLOB. PROP:Touched can be used to determine if the contents of the BLOB has changed since it was retrieved from disk.

Example:

ArchiveFile PROCEDURE

Names   FILE,DRIVER('TopSpeed')

NaneKey  KEY(Name)

Notes    BLOB        !Can be larger than 64K

Rec      RECORD

Name      STRING(20)

        END

       END

 

ArcNames FILE,DRIVER('TopSpeed')

Notes    BLOB      

Rec       RECORD

Name       STRING(20)

         END

        END

 

CODE

SET(Names)

LOOP

 NEXT(Names)

 IF ERRORCODE() THEN BREAK.

 ArcNames.Rec = Names.Rec                               !Assign rec data to Archive

 ArcNames.Notes{PROP:Handle} = Names.Notes{PROP:Handle} !Assign BLOB to Archive

 IF ERRORCODE() = 80

  MESSAGE(‘BLOB size is too large’)

  BREAK

 END

 ArcNames.Notes{PROP:Size} = Names.Notes{PROP:Size}     ! and adjust the size

 ADD(ArcNames)

END

 

StoreFileInBlob PROCEDURE                                !Stores any disk file into a BLOB

DosFileName STRING(260),STATIC

LastRec     LONG

SavPtr      LONG(1)                                      !Start at 1

FileSize    LONG

 

DosFile    FILE,DRIVER('DOS'),PRE(DOS),NAME(DosFileName)

Record      RECORD

F1           STRING(2000)

           END

          END

 

BlobStorage  FILE,DRIVER('TopSpeed'),PRE(STO)

File         BLOB,BINARY

Record        RECORD

FileName       STRING(64)

             END

            END

 

CODE

IF NOT FILEDIALOG('Choose File to Store',DosFileName,,0010b) THEN RETURN.

OPEN(BlobStorage)                     !Open the BLOB file

STO:FileName = DosFileName            ! and store the filename

OPEN(DosFile)                         !Open the file

FileSize = BYTES(DosFile)             !Get size of file

STO:File{PROP:Size} = FileSize        ! and set the BLOB to store the file

LastRec = FileSize % SIZE(DOS:Record) !Check for short record at end of file

LOOP INT(FileSize/SIZE(DOS:Record)) TIMES

 GET(DosFile,SavPtr)                  !Get each record

 ASSERT(NOT ERRORCODE())

 STO:File[SavPtr - 1 : SavPtr + SIZE(DOS:Record) - 2] = DOS:Record

                                      !String slice data into BLOB

 SavPtr += SIZE(DOS:Record)           !Compute next record pointer

END

IF LastRec                            !If short record at end of file

 GET(DosFile,SavPtr)                  !Get last record

 ASSERT(BYTES(DosFile) = LastRec)     ! size read should match computed size

 STO:File[SavPtr - 1 : SavPtr + LastRec - 2] = DOS:Record

END

ADD(BlobStorage)

ASSERT(NOT ERRORCODE())

CLOSE(DosFile);CLOSE(BlobStorage)

 

See Also:

PROP:ImageBlob

PROP:Size

Implicit String Arrays and String Slicing

BLOBtoFILE

FILEtoBLOB

PROP:Handle

PROP:ClientHandle