Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
How to save List Box Data at Runtime (TFileStream) Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
02-Dec-02
Category
VCL-General
Language
Delphi 2.x
Views
173
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
DSP, Administrator
Reference URL:
DKB
			Author: Lou Adler 

How do I save data entered in a list box at run time without resorting to a text 
file or having to deal with the overhead of a table?

Answer:

Note: A sample programhttp://www.delphicorner.f9.co.uk/files/persist.zip is 
available. Even though this article focuses on saving a list box at runtime, it 
really presents a general overview of using the TFileStream class for streaming 
components to and from disk. This is an important distinction to make because while 
I use the TListBox as an example, it is possible to apply the concepts to almost 
all components.

Any OOP class library worth its salt supports what is called streamable persistent 
objects. Simply put, this means that an instance of a class (or at least its data) 
can be saved to a disk file and restored later. When a program reloads the object, 
it is restored in its last state, just prior to being written. The cool thing about 
this is that the program doesn't have to have any advance knowledge of the state of 
the object; the object itself contains all the information it needs to recreate 
itself when it's restored.

For example, let's say you've created a program that has a list box in which people 
append various bits of information at run time. For many folks, saving the 
information to disk means iterating through all the items in the list and writing 
them to a text file or even a table. The program must reload the data from the 
external file and add the data, line by line. This is not so bad, but it can be a 
bit of a chore to write the code.

On the other hand, using object persistence, the same program mentioned above 
instructs the list box to write its data to a disk file of some sort. When it wants 
to reload the object, all it has to do is stream it back into memory and specify 
the base class to write to. Remember, since all the data of the object was saved 
with it when it was written to disk, the object comes back to life in its original 
form. That's the whole idea behind object persistence.

Delphi itself makes heavy use of object persistence. Every time you save a project, 
it streams out to disk the data contained in your objects' properties so that 
everything you set during your session is saved. When you reload a project, Delphi 
streams the object data back into your form(s) to restore everything you previously 
set. In fact, a form file itself is streamed to and from disk. I should note here 
that Delphi uses a couple of specialized stream classes, TWriter and TReader which 
are derived from a superclass called TFiler. I won't go into the details of these 
classes here, since I'm providing a much simpler demonstration of employing object 
persistence in your programs. I'll leave it up to you to research this topic 
further.

Moving on, you might ask, "Where does employing streamable persistent objects come 
in handy?" The most useful cases I've found for employing them are when I've 
written programs that provide parameter or input criteria for processes, where the 
range of possible values to search on remain fairly constant from one run of the 
program to the next.

For instance, in my line of work, almost all of my programs are typically 
front-ends to very complex query operations. However, the range of domains and 
their values don't change very often, and from client to client, the same questions 
are typically asked. So in these cases, I've found that simply streaming my 
criteria objects (these are all list objects) out to disk when I close the forms 
and streaming them back in when I open the forms provides a much cleaner solution 
to saving my criteria sets from session to session. Besides, this is very low 
overhead programming, since once the programs are finished with the streams, 
they're immediately destroyed. Not only that, I don't have to use DB.PAS or 
DBTables.PAS for data operations.

A simple example

The example I've provided here is by no means a full-fledged search program of the 
type I normally write. I've merely taken the parts pertinent to this article for 
your use. Feel free to include or modify this code to your heart's content. In any 
case, here's the code listing for the main form of the program. We'll discuss 
particulars below.

1   unit main;
2   
3   interface
4   
5   uses
6     Windows, Messages, SysUtils, Classes, Graphics,
7     Controls, Forms, Dialogs, StdCtrls;
8   
9   type
10    TForm1 = class(TForm)
11      ListBox1: TListBox;
12      Edit1: TEdit;
13      Memo1: TMemo;
14      procedure Edit1KeyPress(Sender: TObject; var Key: Char);
15      procedure FormCreate(Sender: TObject);
16      procedure FormClose(Sender: TObject; var Action: TCloseAction);
17      procedure ListBox1DblClick(Sender: TObject);
18    private
19      { Private declarations }
20    public
21      { Public declarations }
22    end;
23  
24  var
25    Form1: TForm1;
26  
27  implementation
28  
29  {$R *.DFM}
30  
31  procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
32  begin
33    if Key = #13 then
34    begin
35      Key := #0;
36      ListBox1.Items.Add(Edit1.Text);
37      Edit1.Text := '';
38    end;
39  end;
40  
41  procedure TForm1.FormCreate(Sender: TObject);
42  var
43    strm: TFileStream;
44  begin
45    if FileExists('MyList.DAT') then
46    begin
47      strm := TFileStream.Create('MyList.DAT', fmOpenRead);
48      strm.ReadComponent(ListBox1);
49      strm.Free;
50    end;
51  end;
52  
53  procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
54  var
55    strm: TFileStream;
56  begin
57    strm := TFileStream.Create('MyList.DAT', fmCreate);
58    strm.WriteComponent(ListBox1);
59    strm.Free;
60  end;
61  
62  procedure TForm1.ListBox1DblClick(Sender: TObject);
63  begin
64    ListBox1.Items.Delete(ListBox1.ItemIndex);
65  end;
66  
67  end.


You were expecting some complex code, weren't you? In actuality, this stuff is 
incredibly simple. So why isn't it documented very well? I'd say it's because this 
is one of the more uncommon things done in Delphi. But for those of you who wish to 
really get into the innards of the environment, this stuff is a must to understand 
and master. Let's look a little deeper into the code.

The program consists of a form with a TEdit and a TListBox dropped onto it. It has 
just two meaningful methods: FormCreate and FormClose. In the FormCreate method,
68  
69  procedure TForm1.FormCreate(Sender: TObject);
70  var
71    strm: TFileStream;
72  begin
73    if FileExists('MyList.DAT') then
74    begin
75      strm := TFileStream.Create('MyList.DAT', fmOpenRead);
76      strm.ReadComponent(ListBox1);
77      strm.Free;
78    end;
79  end;


the program checks for the existence of MyList.DAT with a call to FileExists, which 
is the stream file that holds the list box information. If it exists, the file is 
streamed into ListBox1; otherwise, it does nothing. With the FormClose method,
80  
81  procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
82  var
83    strm: TFileStream;
84  begin
85    strm := TFileStream.Create('MyList.DAT', fmCreate);
86    strm.WriteComponent(ListBox1);
87    strm.Free;
88  end;


the program writes ListBox1 out to MyList.DAT, overwriting any previous versions of 
the file.

That's all there is to this program. Surprisingly, this is one of the more simple 
things to do in Delphi, but paradoxically it's one of the most difficult things to 
find good information about in the manuals or help file. Granted, as I mentioned 
above, doing this type of stuff is fairly uncommon, but think of the implication: 
simple, low overhead, persistent storage without the need for tables. What was 
accomplished above was done in fewer than 10 lines of code — that's absolutely 
incredible!

I urge you to play around with this technique and apply it to other things. I think you'll get a lot of mileage out of it.

			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC