1 Introduction
Currently, the traditional layer-2 C/S (Client/Server) Architecture Application Software has developed into a multi-layer distributed application.
System [2]. To improve system efficiency and system scalability, many software developers
Some basic data is distributed to various clients. The advantage of this working mode is significant because it reduces
Non-real-time data (such as employee tables and Product Data Tables) flows over the network. When the network is paralyzed
The user can still maintain part of the work. At the same time, this mode requires regular data between the client and the server.
To update data more effectively, we imagine creating a database similar to a briefcase on the client, that is
Like SQL server on the server, all data tables are stored in several files. This document provides details about this issue.
The storage principle of OLE structured files is analyzed in detail, and a series of related files are discussed in depth in the Delphi environment.
Operation.
2. Storage principle and operation of OLE composite documents
2.1 How Ole composite documents are stored
Ole (Object Linking and Embedding), short for object connection and embedding, is in a Windows Environment
To share data between different Windows applications. Ole structured file, also known as Ole
In simple terms, the structure of the OLE composite document actually means that its content is stored according to stream and
Storage mode. Microsoft Word and Excel files are typical Ole composite documents,
1. The content of this document is similar to the file system in the operating system.
". The "folder" is called storage, and the continuous data contained in each storage is called a "file" as a stream.
Because each "file" in the OLE compound document is independent of each other, the questions raised in the introduction are very good.
To solve this problem, we first create an ole composite document, and then store a large number of data tables in the form of a stream to the composite
In this way, the client and server only transmit several files when updating data, which is very effective. And,
When we write a data table in paradox 7 format to the OLE composite document, we find that the content of the OLE composite document
The data volume is about 50% of the total capacity of many original data tables.
Ole composite document ----- myoledoc. Ole
Database ----- Storage
Employee ----- stream
Customer Ole data
Excel or AutoCAD data
2.2 Establishment of OLE composite document
You can use the Windows SDK function stgcreatedocfile to create an ole composite document.
ActiveX unit. The original form of the function is:
Function stgcreatedocfile (pwcsname: polestr; grfmode: longint; reserved: longint; out stgopen: istorage): hresult; stdcall;
The storage returned by the function is the root directory of the composite document. The specific parameters are as follows:
(1) wcsname: name of the file to be created;
(2) grfmode: Operation Method of the composite document. The meanings of the selected values are shown in table 1:
(3) Reserved: The value must be set to 0;
(4) stgopen: returns a storage;
// The grfmode parameter has the following meanings:
Stgm_read read-only mode
Stgm_write write only mode
Stgm_readwrite read/write mode
Stgm_share_deny_none shared access mode
Stgm_share_deny_read: the shared read mode is prohibited.
Stgm_share_deny_write: the shared write mode is prohibited.
Stgm_share_exclusive Access Mode
Stgm_direct takes effect immediately for all modifications to the composite document
Stgm_transacted is saved to the composite document only when all modifications are submitted.
Stgm_failifthere if a stream or storage exists, the composite document creation fails.
Stgm_create if a stream or storage exists, it will be overwritten; otherwise, a new stream or storage will be created.
Stgm_deleteonrelease when the stream or storage in this composite document is released, it will also be released automatically
2.3 open the OLE compound document
You can use the Windows SDK function stgopenstorage to open an ole composite document.
ActiveX unit. The original form of the function is:
Function stgopenstorage (pwcsname: polestr; stgpriority: istorage;
Grfmode: longint; snbexclude: tsnb;
Reserved: longint; out stgopen: istorage): hresult; stdcall;
Here, snbexclude selects nil. For other parameters, see stgcreatedocfile ().
2.4 stream creation and Data Writing
After opening an ole composite document, you can use the createstream function of the istorage interface to create
And then use the powerful Stream Mechanism of Delphi to exchange information with the data of various ole-based applications.
For example, you can use the olecontainer control in Delphi to load data that supports Ole applications,
Then, the savetostream () method under the control is called to write the information into the composite document as a stream. Createstream Function
The prototype of the number is:
Function createstream (pwcsname: polestr; grfmode: longint;
Reserved1: longint; reserved2: longint;
Out STM: istream): hresult; stdcal;
Where, pwcsname refers to the name of the new stream. The values of the reserved1 and reserved2 parameters are set to 0. For other parameters, see stgcreatedocfile ().
2.5 storage of OLE composite documents
As mentioned above, the storage of OLE composite documents is similar to the "folder" of the file system in concept. It also has
Create, open, and delete operations. The createstorage () and openstorage () functions using the istorage interface can
To create or open a sub-storage separately. Their prototype is:
Function createstorage (pwcsname: polestr; grfmode: longint;
Dwstgfmt: longint; reserved2: longint; out STG: istorage): hresult; stdcall;
Function openstorage (pwcsname: polestr; const stgpriority: istorage;
Grfmode: longint; snbexclude: tsnb; reserved: longint;
Out STG: istorage): hresult; stdcall;. Their parameters are the same as those above.
See the source code section.
2.6 Delete storage and stream
You can use the destroyelement () function of the istorage interface to delete the storage or stream of OLE composite documents.
Prototype:
Function destroyelement (pwcsname: polestr): hresult; stdcall;
The pwcsname parameter indicates the name of the deleted storage or stream. It should be noted that when you delete the storage or stream of a composite document
The interface of the destroyelement () function should be the last storage of the deleted storage or stream. 1. To delete
For the "customer" stream, the correct statement is: database-destroyelement ('customer'); to delete
In addition to the "Database" storage, you should use rootstorage-destroyelement ('database'), where
Rootstorage is the root directory storage. In addition, when a stream or storage is deleted, its data is not physically deleted,
3 main source code
This program will create a composite document named myoledoc. Ole. In this composite document, there is a composite document named
Database storage, which stores two streams: employee and customer, which correspond to two data tables respectively,
1.
3.1 controls and attributes:
(1) Add ActiveX and axctrls to the interface reference of unit1. declare a global variable.
Duqu: Boolean = true; this variable is used to record whether the customer stream is deleted.
(2) The related controls and properties involved in the program are shown in table 2.
Control name class property name value
Table1 tTable databasename c: \ Ole (data table Storage path) tablename employee. DB
Table2 tTable databasename c: \ Ole (data table Storage path) tablename customer. DB
Datasetprovider1 tdatasetprovider dataset Table1
Datasetprovider2 tdatasetprovider dataset Table2
Clientdataset1 tclientdataset providername datasetprovider1
Clientdataset2 tclientdataset providername datasetprovider2
Clientdataset3 tclientdataset relies on loadfromstream () of clientdataset3 and clientdataset4 ()
The clientdataset4 tclientdataset method reads two data tables from the composite document. The two controls use the default values.
Table 1: Main controls and properties in the program
3.2 main code
(1) programming bitbtn1 onclick events; Creating composite documents, storage, and streams; and saving two data tables
To this composite document.
Procedure tform1.bitbtn1click (Sender: tobject );
VaR // declare related variables
HRE: hresult;
Rootstorage, substorage: istorage;
Istr1, istr2: istream;
Olestream1: tolestream;
Begin
HRE: = stgcreatedocfile ('myoledoc. ole', stgm_create or stgm_readwrite or
Stgm_direct or stgm_share_exclusive, 0, rootstorage); // create a name named
// Myoledoc. Ole composite document
If not succeeded (HRE) Then application. Terminate; // the function of the succeeded () function is
// Whether the composite document has been created successfully
HRE: = rootstorage. createstorage ('database', stgm_create or stgm_readwrite or
Stgm_direct or stgm_share_exclusive, substorage); // create
// Database storage
If not succeeded (HRE) Then application. Terminate; // determine whether the storage is successfully created.
HRE: = substorage. createstream ('employee ', stgm_create or stgm_readwrite or
Stgm_direct or stgm_share_exclusive, 0, 0, istr1); // create
// Stream
If not succeeded (HRE) Then application. Terminate; // determines whether the stream is successfully created.
Clientdataset1.active: = true;
Olestream1: = tolestream. Create (istr1 );
Clientdataset1.savetostream (olestream1); // write data from the employee data table
// Store the myoledoc. Ole composite document in the database and save it as a stream named "employee"
Olestream1.free;
HRE: = substorage. createstream ('customer', stgm_create or stgm_readwrite or
Stgm_direct or stgm_share_exclusive, 0, istr2 );
If not succeeded (HRE) Then application. Terminate;
Clientdataset2.active: = true;
Olestream1: = tolestream. Create (istr2 );
Clientdataset2.savetostream (olestream1); // write data from the customer data table
// Store the myoledoc. Ole composite document in the database and save it as a stream named customer
Olestream1.free;
Duqu: = true;
End;
(2) program The onclick event of bitbtn2. Open the composite document, storage, and stream, and read two data tables from the composite document.
Procedure tform1.bitbtn2click (Sender: tobject );
VaR
HRE: hresult;
Rootstorage, substorage: istorage;
Istr1, istr2: istream;
Olestream1: tolestream;
Begin
Clientdataset4.active: = false;
Clientdataset4.active: = false;
HRE: = stgopenstorage ('myoledoc. ole', nil, stgm_readwrite or stgm_direct or
Stgm_cmd_exclusive, nil, 0, rootstorage); // open a composite file named myoledoc. Ole.
If not succeeded (HRE) Then application. Terminate; // determines whether the composite document is successfully opened.
HRE: = rootstorage. openstorage ('database', nil, stgm_readwrite or stgm_direct or
Stgm_cmd_exclusive, nil, 0, substorage); // open a storage named Database
If not succeeded (HRE) Then application. Terminate; // determines whether the storage is successfully opened.
HRE: = substorage. openstream ('employee ', nil, stgm_readwrite or stgm_direct or
Stgm_share_exclusive, 0, istr1); // open a stream named "employee ".
If not succeeded (HRE) Then application. Terminate; // determines whether the stream is successfully opened.
Olestream1: = tolestream. Create (istr1 );
Clientdataset3.loadfromstream (olestream1); // from the database of myoledoc. Ole composite document
// Store, read the employee stream, and send the data to the clientdataset3 component;
Olestream1.free;
Clientdataset3.active: = true;
If duqu then
Begin
HRE: = substorage. openstream ('customer', nil, stgm_readwrite or stgm_direct or
Stgm_clu_exclusive, 0, istr2 );
If not succeeded (HRE) Then application. Terminate ;;
Olestream1: = tolestream. Create (istr2 );
Clientdataset4.loadfromstream (olestream1); // from the database of myoledoc. Ole composite document
// Store, read the customer stream, and send the data to the clientdataset4 component;
Olestream1.free;
Clientdataset4.active: = true;
End;
End;
(3) program The onclick event of bitbtn4;/delete a stream in the composite document
Procedure tform1.bitbtn4click (Sender: tobject );
VaR
HRE: hresult;
Rootstorage, tempstorage, substorage: istorage;
CLS: tclsid; // It is a unique 16-byte number.
Sta: tstatstg; // Save the information returned by istorage. Stat ()
Istr1: istream;
Begin
HRE: = stgopenstorage ('myoledoc. ole', nil, stgm_readwrite or stgm_direct or
Stgm_cmd_exclusive, nil, 0, rootstorage );
If not succeeded (HRE) Then application. Terminate;
Rootstorage. Stat (STA, 0); // istorage. Stat () returns a lot of root directory storage Information
CLS: = Sta. CLSID; // obtain the unique identifier of the root directory.
HRE: = rootstorage. openstorage ('database', nil, stgm_readwrite or stgm_direct or
Stgm_cmd_exclusive, nil, 0, substorage); // open a storage named Database
Substorage. destroyelement ('customer'); // Delete the myoledoc. Ole composite document database
// Store the customer stream
HRE: = stgcreatedocfile ('myoledoctemp. ole', stgm_create or stgm_readwrite or
Stgm_direct or stgm_clu_exclusive, 0, tempstorage); // create
// Myoledoctemp. Ole temporary composite document
If not succeeded (HRE) Then application. Terminate;
Rootstorage. copyto (0, nil, nil, tempstorage); // copy the contents of the myoledoc. Ole composite document to
// Composite document
Rootstorage: = nil; // leave the root directory storage of the myoledoc. Ole composite document empty to re-establish
// Document combination
HRE: = stgcreatedocfile ('myoledoc. ole', stgm_create or stgm_readwrite or
Stgm_direct or stgm_share_exclusive, 0, rootstorage); // create a name named
// Myoledoc. Ole composite document
If not succeeded (HRE) Then application. Terminate;
Rootstorage. setclass (CLS); // set the CLSID of the new document to the CLSID of the original document.
Tempstorage. copyto (0, nil, nil, rootstorage); // copy the content of the temporary composite document to the new composite File
// File in progress
Tempstorage: = nil; // leave the root directory of the temporary composite document empty so that you can delete it.
Deletefile ('myoledoctemp. ole ');
Duqu: = false;
End;
//////////////////////////////////////// /////////////////////////////////////
// Example 2: read/write composite documents in Structured Storage
//////////////////////////////////////// /////////////////////////////////////
Uses ActiveX;
Type
TREC = record
Name: String [8];
Age: word;
End;
Const filename = 'C: \ temp \ test. dat ';
Procedure tform1.formcreate (Sender: tobject );
Begin
Button1.caption: = 'write composite file ';
Button2.caption: = 'read composite file ';
Position: = pow.topcenter;
End;
Procedure tform1.button1click (Sender: tobject );
Const
Mode = stgm_create or stgm_readwrite or stgm_1__exclusive;
VaR
Stgroot, stgsub: istorage;
STM: istream;
Rec1: TREC;
Begin
{Create a root istorage: stgroot}
Stgcreatedocfile (filename, mode, 0, stgroot );
{Create sub-istorage: stgsub}
Stgroot. createstorage ('stgsub', mode, 0, 0, stgsub );
{Create istream: sTM in sub-istorage: stgsub}
Stgsub. createstream ('stm ', mode, 0, 0, STM );
{Write data}
Rec1.name: = 'zhang san ';
Rec1.age: = 99;
STM. Write (@ rec1, sizeof (TREC), nil );
End;
Procedure tform1.button2click (Sender: tobject );
Const
Mode = stgm_read or stgm_share_exclusive;
VaR
Stgroot, stgsub: istorage;
STM: istream;
Rec1: TREC;
Begin
{Exit if it is not a structured storage file}
If stgisstoragefile (filename) <> s_ OK then exit;
{Get the root istorage: stgroot}
Stgopenstorage (filename, nil, mode, nil, 0, stgroot );
{Get sub-istorage: stgsub; note: the name of the first parameter must be consistent with that of the saved parameter}
Stgroot. openstorage ('stgsub', nil, mode, nil, 0, stgsub );
{Get istream: STM; note: the name of the first parameter must be consistent with that of the saved parameter}
Stgsub. openstream ('stm ', nil, mode, 0, STM );
{Read data}
STM. Read (@ rec1, sizeof (TREC), nil );
Showmessagefmt ('% s, % d', [rec1.name, rec1.age]);
End;
End.