Up to now, our programs have depended on us, the programmer, to
give them data to work with. This wouldn't work very well for a
phone book program. The user should be the one to fill in the names
and phone numbers. QBASIC will let us get information from the user
with INPUT. But when the program ends, that information is gone.
Writing to a file
The solution to this problem is to let the user enter their information,
then the program will store that information in a file on the hard disk.
QBASIC offers a number of ways to do this. Try this:
INPUT "Enter your name: ", Name$ OPEN "testfile.txt" FOR OUTPUT AS #1 WRITE #1, Name$ CLOSE #1
When you run that program, and enter your name, it will place your
name in a file on the hard disk called "testfile.txt". You can use
Notepad to find it and make sure your name is there. You might need
to figure out where QBASIC put the file. That can be a little
tricky. If you exit QBASIC, and from the DOS prompt enter this:
type testfile.txt
You should see your name, or whatever you entered. The "type" command
at the DOS prompt copies the contents of a file to the screen. You could also
try this:
notepad testfile.txt
That should bring up notepad with your file. When you are working with
files, it is a good idea to know how to bring them up in notepad. This
way you can look at them to see if they contain what you expected.
OPEN, WRITE, and CLOSE
There are three statements, OPEN, WRITE, and CLOSE that are needed
to write information to a file. The OPEN statement tells QBASIC three things:
- The name of the file (testfile.txt)
- Whether we want to write to the file (OUTPUT) or read
from the file (INPUT)
- The file number (#1 in this example)
Once the file is opened, we will use the file number to let QBASIC know
which file we want to write to. You could have many files open at the
same time, so the file number lets QBASIC know which file you want to
work with.
The WRITE statement tells QBASIC which file we want to write to (#1),
and what we want to write (Name$). It is very much like a PRINT statement,
but instead of sending the information to the screen, WRITE sends the
information to a file.
Finally, we need to CLOSE the file, to let QBASIC know that we are
done. Otherwise, QBASIC might not write anything to the file at all.
The CLOSE statement only needs to know which file you want to close,
so it only requires the file number.
Reading from a file
The following
program will get the name and print it on the screen:
OPEN "testfile.txt" FOR INPUT AS #1 INPUT #1, Name$ CLOSE #1 PRINT Name$
There are three main things that are different in this
program if you compare it to the previous program.
- The OPEN statement uses "INPUT" instead of "OUTPUT".
This tells QBASIC that we plan to get data from the
file.
- The INPUT statement, which you've seen before, is
used to read from a file. The #1 tells it that we
want to read from file #1. When we've used INPUT
in other programs, there was no #1. Without a
file number, INPUT gets information from the
keyboard. With a file number, it gets information
from a file.
- Instead of getting something from the user at the
beginning of the program, we display what was read
from the file at the end with a good ol' PRINT
statement.
One thing that hasn't changed at all is the CLOSE
statement. We CLOSE file #1 so that QBASIC knows we
are done with it. While we probably won't lose any data
if we don't CLOSE in this case, it is still a good thing
to do. QBASIC can only open so many files, so if you leave
some open, you might not be able to open any more.
Logging
Sometimes it can be very useful to write to a file
while a program is running so that you can look at
what happened later. This is called "logging". We can
use the "APPEND" option in the OPEN statement to open
a file and simply keep adding to the end of it.
OPEN "logfile.txt" FOR APPEND AS #1 PRINT #1, "Program Run: "; TIME$ CLOSE #1
CLS INPUT "What is your name"; Name$ PRINT "Hello, "; Name$
OPEN "logfile.txt" FOR APPEND AS #1 PRINT #1, "Program Stopped: "; TIME$ CLOSE #1
We've logged two things in this program, the
program's start time, and it's end time. Run the
program a few times, then exit QBASIC and type:
notepad logfile.txt
That will show you what is in your log.
Input Files
Ideas: Fortune Teller using a text file as input. This
would combine file input with arrays.
Keeping Track of Things
Let's say we want our program to remember who it
is registered to. We also want it to count how many times
it has been run. We could try something like this:
CLS INPUT "Enter your name to register this program: ", Name$ PRINT "Thank you, "; Name$ RunCount = RunCount + 1 PRINT "This program is registered to: "; Name$ PRINT "This program has been run"; RunCount; "times." PRINT "We hope you have enjoyed it."
But that doesn't work. Why? Because QBASIC can't
remember the value of the variables Name$ and RunCount from
one run of the program to the next.
To fix this, we need to use a file. We can read the
file before the program starts, and write the file back
out when the program is finished. We will save the
user's name and the number of times the program has been
run in this file.
The code to do this is a bit more complex than what we've
done so far. This is because QBASIC handles file errors
in a strange way. Our program must handle one file error.
The first time it is run, there will be no registration file
for it to read. So the OPEN will fail. We have to handle
this, or our program won't work.
' If there are any problems, QBASIC will jump to ErrorHandler below. ON ERROR GOTO ErrorHandler
' This is the error code that is filled in by the error handler DIM ErrorCode AS INTEGER
CLS
' Always reset this before doing something you want to check ErrorCode = 0 ' Try to get the name and run count from the file OPEN "register.txt" FOR INPUT AS #1
' If the file wasn't found IF ErrorCode = 53 THEN ' Get the name from the user INPUT "Enter your name to register this program: ", Name$ PRINT "Thank you, "; Name$ ' And set the run count to 0 RunCount = 0 ELSE ' Get the user's name and the run count from the file INPUT #1, Name$, RunCount CLOSE #1 END IF
RunCount = RunCount + 1 PRINT "This program is registered to: "; Name$ PRINT "This program has been run"; RunCount; "times." PRINT "We hope you have enjoyed it."
' Save the name and run count for the next run OPEN "register.txt" FOR OUTPUT AS #1 WRITE #1, Name$, RunCount CLOSE #1
' This END prevents us from running the error handler at the ' end of the program. It causes the program to stop, just ' like pressing the Break key. END
' QBASIC will jump here if an error occurs ErrorHandler: ' We have to move the error code into a variable or we won't ' see it because ERR is set to zero after the handler is done. ErrorCode = ERR RESUME NEXT
Handling File Errors
"ON ERROR GOTO ErrorHandler" tells QBASIC that if there
is a problem, the program should immediately jump to "ErrorHandler:"
which you will see near the end of the program. There we can get the
error code which is in a QBASIC variable called "ERR" and copy
it to our own variable "ErrorCode". If we don't do this, we
will lose the error code stored in ERR. RESUME NEXT tells
QBASIC to continue from where the error occurred.
I try very hard to avoid using GOTO in my programs.
Programs that use GOTO can be very hard
to understand.
Unfortunately, in this case, QBASIC leaves us with no
alternative. We have to use a GOTO. So, I've tried to
come up with the simplest
solution that keeps the code from being too hard to follow.
With this little error handler in place, we can simply
assume that ErrorCode will contain the error number when
something goes wrong. Just don't forget to reset it
or you will be looking at old errors!
Binary I/O
As opposed to...
How to do it.
What is the difference? Unformatted, unreadable.
Why is it a good thing? Small, unreadable to prying eyes, fast.
Sample: Write out a few numbers and strings. Examine with notepad.
Read them back in.
Random I/O
Up to this point we have been using what is called "Sequential
I/O". Sequential means "one after another". I/O stands for
Input/Output. When we write the user's name and the run count to
the file, we write them one after another. This is sequential
output. When we read the name and run count, we read them one
after another. Name first, then run count. This is sequential
input. All together, this adds up to Sequential Input and Output,
or Sequential I/O.
Random I/O lets you read and write data to any part of a file
in any order you want. It is very useful when you have very
large files, and you don't have enough time or memory to read
everything in the file sequentially (one after another).
Random I/O lets you jump right to the data you want in a file,
and read or write it.
Even in very large and complex programs, Random I/O is rarely
used due to its complexity. Imagine if the program has a bug
and it writes to the wrong location in the file. The file
could be destroyed because of this. We won't cover Random I/O
here. But, if you need it, it's in QBASIC.
Source: http://jpsor.ucoz.com |