Opening streams

Streams contain the raw data of an OLE object. You would not want to alter a stream created by a server application. However, you can add your own streams to storage files. These streams can store information about the storages. You can write streams that provide labels for each storage or write a stream that lists the members of the storage.

To access a stream in an OLE storage file, you define a stream variable and instantiate it. Then you open a stream from a storage that has already been opened. Opening a stream establishes a connection between the stream variable and the stream data within a storage.

The following code declares and creates OLEStorage and OLEStream variables, opens the storage, and then opens the stream:

integer result
OLEStorage stg_pic
OLEStream stm_pic_label
/***************************************************
Allocate memory for the storage and stream variables
***************************************************/
stg_pic = CREATE OLEStorage
stm_pic_label = CREATE OLEStream
/***************************************************
Open the storage and check the return value
***************************************************/
result = stg_prod_pic.Open("picfile.ole")
IF result <> 0 THEN RETURN
/***************************************************
Open the stream and check the return value
***************************************************/
result = stm_pic_label.Open(stg_prod_pic, &
   "pic_label", stgReadWrite!)
IF result <> 0 THEN RETURN

PowerBuilder has several stream functions for opening and closing a stream and for reading and writing information to and from the stream.

Table 19-11: Stream functions

Function

Result

Open

Opens a stream into the specified OLEStream variable. You must have already opened the storage that contains the stream.

Length

Obtains the length of the stream in bytes.

Seek

Positions the read/write pointer within the stream. The next read or write operation takes place at the pointer.

Read

Reads data from the stream beginning at the read/write pointer.

Write

Writes data to the stream beginning at the read/write pointer.

If the pointer is not at the end, Write overwrites existing data. If the data being written is longer than the current length of the stream, the stream’s length is extended.

Close

Closes the stream, breaking the connection between it and the OLEStream variable.

Example: writing and reading streams

This example displays a picture of a product in the OLE control ole_product when the DataWindow object dw_product displays that product’s inventory data. It uses the file constructed with the utility application described in the earlier example (see “Example: building a storage”). The pictures are stored in an OLE storage file, and the name of each picture’s storage is also the product identifier in a database table. This example adds label information for each picture, stored in streams whose names are the product ID plus the suffix _lbl.

Figure 19-6 shows the structure of the file.

Figure 19-6: OLE storage file structure

The example shows an OLE storage file called PICTURES DOC OLE, containing three substorages, product 1, product 2, and product 3, and three streams called product 1 _ lbl, product 2 _ lbl, and product 3 _ lbl.

The example has three scripts:

The OLEStorage variable stg_prod_pic is an instance variable of the window:

OLEStorage stg_prod_pic

The script for the window’s Open event is:

integer result
stg_prod_pic = CREATE OLEStorage
result = stg_prod_pic.Open( is_ole_file)

The script for the RowFocusChanged event of dw_prod is:

integer result
string prodid, labelid, ls_data
long ll_stmlength
OLEStream stm_pic_label
/***************************************************
Create the OLEStream variable.
***************************************************/
stm_pic_label = CREATE OLEStream
/***************************************************
Get the product id from the DataWindow.
***************************************************/
this.Object.prod_id[currentrow]
/***************************************************
Open the picture in the storage file into the
control. The name of the storage is the product id.
***************************************************/
result = ole_prod.Open(stg_prod_pic, prodid)
IF result <> 0 THEN RETURN
/***************************************************
Construct the name of the product label stream and
open the stream.
***************************************************/

labelid = prodid + "_lbl"
result = stm_pic_label.Open( stg_prod_pic, &
   labelid, stgReadWrite! )
IF result <> 0 THEN RETURN
/***************************************************
Get the length of the stream. If there is data
(length > 0), read it. If not, write a label.
***************************************************/
result = stm_pic_label.Length(ll_stmlength)
IF ll_stmlength > 0 THEN
   result = stm_pic_label.Read(ls_data)
   IF result <> 0 THEN RETURN
   // Display the stream data in st_label
   st_label.Text = ls_data
ELSE
   result = stm_pic_label.Write( labelid )
   IF result < 0 THEN RETURN
   // Display the written data in st_label
   st_label.Text = labelid
END IF
/****************************************************
Close the stream and release the variable's memory.
***************************************************/
result = stm_pic_label.Close()
DESTROY stm_pic_label

The script for the window’s Close event is:

integer result
result = stg_prod_pic.Save()
DESTROY stg_prod_pic