In this tutorial you will be shown the basics of reading and writing data to files. If you know everything here, there's an extension of this tutorial, which also goes into the Delphi OpenDialog and SaveDialog components (not covered in the tutorial you are presently reading) and, important general skills, creating your own "pop-up" (not in the Windows sense), modal dialog boxes, and passing values between forms / units. (Also not covered in this tutorial.)
Written using Delphi 4, but the points here should be valid in any version apart from 1. (Most points valid even there!)
This "tutorial" will be less "helpful" than is typical for the tutorials on the site it comes from.
Rather than a "how you do it", it is a "here's one I did earlier".
The sourcecode is much more heavily commented than usual. Those comments are "the tutorial" this time.
Some of the techniques demonstrated are specific to the task the application was built for. In addition, you will see other "tricks of the trade".
There are many ways to read and write data to files... and I have written several tutorials on the subject. The method shown here works with text files. It is more labor intensive than the "put text in a memo" approach, but it also handles huge files... potentially as big as your hard drive... with less strain on your memory. It also introduces you to concepts that you can use to handle non-text data.
Over the years I've written several tutorials on file handling, among them another tutorial that covers some of the same ground covered by this tutorial. You may want to give it a try to help consolidate things you learned here. Some of the others cover quite different approaches to data file handling.
The objectives of the application are as follows. You can skim the next two paragraphs, because they are just to explain the precise details of why I wrote the application. Then I turn to the general aspects of the application so that you can see to what sorts of jobs you might apply the techniques in it.
My weather logging system creates a text file with a line of text for each weather observation. If the system is rebooted for any reason, the data log is used to rebuild the graph of the past week's weather. (By the way, my FarWatch system allows you to see my weather logging software in action.)
From time to time, I "harvest" old data, copying it onto an external hard drive. I then massage the data file on the system recording the weather data, deleting the lines relating to events more than a week old.
So, in general, what this application does is...
The application will do nothing to the source file... the application will only be read from it.
Because it decides many issues, and because for my needs, I can, at this early stage I am deciding that the application will work as follows:
Until a certain line of the source file, nothing will be copied. From that line onward everything will be copied. The definition of "certain line" will be dealt with in a moment.
If you had different needs in mind, don't despair. As long as the order of the lines in the two files is the same, it won't be hard to adapt the application in this tutorial to make it satisfy other requirements. As an artificial example, it would be easy, for instance, to generate a destination file holding every fifth line from the source file.
Another thing that may or may not affect how much work you have to do is the fact that I am going to be working with data from a text file. It is actually produced by another application, but could in theory be created with Notepad, or the superior Textpad.
The textfile is just....
One partridge Two pears Three French hens
... and care was taken to have nothing after the final "s". That was saved in the root of my hard drive as "TmpTest.txt".
So, the plan... and you do always have a plan before you start programming, don't you.... is as follows. You may think I'm merely repeating the outline I gave a moment ago, but compare them. Each contributes details lacking from the other. The first concentrated on what the human user needed to know. The following list addresses things the programmer will need.
Details of how we are going to access the data, and of some variables in the program will help you see how the above is going to work.
(An aside: Ha! I've been writing variations of this program in one guise or another for 25 years(!). I still managed to forget the line marked with the asterisk (*)! I discovered the omission while I was building the application up a step at a time, testing after each step. Without the code mandated by that line, the application fails to write the last line of data from the source file to the destination file. Such things are very, very easy to miss, which is why I was using the very, very simple source file for my tests.)
As I said, I've been writing versions of this program for many years. There's one critical part that is easy to get wrong, so, because I needed to be sure of a detail, I wrote a little application as follows, as preparation for writing the application which is the main subject of this tutorial.
Before the little application can be tested, a small textfile needs
The whole "application" is in the OnClick handler for one button! It is as follows....
procedure TForm1.Button1Click(Sender: TObject); var dfIn:textfile; sTmp:string; boFileEmpty:boolean; begin assignfile(dfIn,'C:\TmpTest.txt'); reset(dfin);//Opens for read repeat readln(dfIn,sTmp); showmessage(sTmp); boFileEmpty:=eof(dfIn); until boFileEmpty; closefile(dfIn); end;
Two lines of that....
boFileEmpty:=eof(dfIn); until boFileEmpty;
... could be turned into one, and a variable done away with....
....but I've done it as above because we are going to use something similar in our bigger program where the simple answer won't do. ("EOF" stands for End Of File, and it is at the root of hours of programmer frustration. Does it become true as soon as you have read the last line of the file, or when you try to read again after the last read that was possible? Different systems work in different ways. (But not as long as you stick to Delphi, thank heavens!)
The first two letters of the variable's name, "boFileEmpty", come from the variable's Boolean type. As a Boolean variable, it can hold "true" or "false".
Now we can develop our "what the program does" statement a little more. Always start in general, non-computer, terms (even while you keep an eye on where you are going to go). But you do eventually have to write code, and pseudo-code like the following can be written faster and examined for flaws in your logic. Get the plan right before you start coding!!
That's about all you need to know that isn't in the sourcecode. The only thing left is to talk a moment about my "line wanted" criterion.... one that you will probably replace with one of your own, relevant to your data, your needs.
The lines in my file are all date-stamped.
A typical line is....
In that line, the first two characters tell us what sort of reading the line holds. The next 7 characters give a date and a time, the "datestamp", by which I mean in this to imply date-and-time stamp. You don't need to worry about how it is coded.
Characters 3-9 almost always hold a datestamp. The only exception is lines beginning cm (for "CoMment"), which can have anything after the "cm".
The lines in the file are always in chronological order.
When I run the application, my criterion for "the" line from which I start copying will simply be "Is this a line after a particular date/time?" That sounds so modest as I write it. This essay isn't (sorry) primarily for you. It is a byproduct of my creation of the application that I actually need still, at the time I write this. Why do I suspect that my "simple" little criterion is going to give me a headache? We'll see. In the simple version of this application, produced for this tutorial, I have kludged things... a perfectly respectable way to build an application in controlled stages. For now the only test data that the application has to "chew on" will be the simple "One partridge, Two pears..." file. And the "Should I start copying lines from source to destination" test will be "Does the line NOT start with a capital "oh" (O)?" When THAT much is working, I will take the next step, refine the boLineIsWanted function and point the application at data that is more complex.
Already, I can see that a step has been left out of my plan. Before the "Repeat", I need to tell the application what record date is the date after which copying of lines should start.
Note I said "date after which...", not "date on which..."?
It is usually wiser to use such criteria. Suppose I said that copying should start when the record date is, say, 10 December 2007. What if the computer was down on the 10th, and there were no lines for that day? It is much safer to say "Copy everything created after (and including) 9 December." If there were lines from the 10th, they'll get copied. If there were no new lines after the 9th until, say, the 12th, the program, written as I have done it, will work fine. Make your criteria "is it more than?" or "is it less than?", and use "is it equal to?" only in certain cases where that is necessary.
Another "detail": Note I said we would be copying all lines from and including the first line with a datestamp after the 9th? In this case, missing one line would hardly matter, but in many cases it would matter considerably... and it is easy to program things so that the first line (or the last) is missed out.
The program uses the enabled property of several buttons to ensure that users do only what is sensible.
The form has the following buttons....
I had the form, the interface between my application and its users, in mind before I ever began designing the code, or even the outline which led to the code. As you gain programming experience, you will be able to design forms FIRST, which is the way to go. Think about your USERS (customers). What do they want? Make the application give them that. The code which makes the things on the form do what they do can come SECOND. (Of course, it takes a little while to reach the point where you don't come up with forms which have buttons like "Give me $100000" or "Fly me to the moon." As your knowledge of what the computer can do (on the surface, and behind the scenes), your ability to design do-able forms will grow. But, even from the start, TRY to work from interface to code.
(The files will be closed after the copy is done, as part of the "Copy lines..." button's OnClick handler, but there's not button for that as the human users shouldn't be troubled with that computing detail. Any more than they were troubled with the opening of the files when the files were specified.)
When the application starts, only the "Specify source file" button is enabled. "Copy lines to..." doesn't get enabled until all of the other steps have been completed.
The programmer must remember that users might backtrack. I.e. the "Specify source file" button might be clicked again after a user had already done that, and, say, the next two steps once already. Providing for all of the paths a user might take through an application can be a real pain. The boDFInIsOpen and boDFOutIsOpen variables are examples of that sort of pain.
That's as far as I'm taking DE41. It shows you how to do a lot of things, and does fully "do" something... eve if that something is a little limited.
In a more advanced tutorial, I am going to start with what we have at the end of this tutorial, and refine it. I will add the "real" boLineIsWanted (one capable of reading a date), and I will extensively extend both the procedure for specifying the source file and the procedure for specifying the destination file. Along the way you will be shown how to use the valuable and easy- to- use (once you know how!) OpenDialog and SaveDialog. And almost "accidentally", along the way I learned... and pass on to you... how to create a modal dialog of your own. ("Modal dialog"? One of those "windows" that pop up to get some information from you, and then go away when the information is supplied.)
That's it for now! Oh dear. Another abrupt end. Should I write something frilly, or go work on another tutorial? Answers on the back of a ten dollar bill, please?
Click here to visit editor's freeware, shareware page.
Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org
....... P a g e . . . E n d s .....