home *** CD-ROM | disk | FTP | other *** search
- Chapter 11 Filing Around
-
-
-
-
- Up to this point, you've seen how CLIPS can work with facts that have been
- entered from the keyboard or rules. However, in some cases you may
- wish to read or write facts to disk. In this chapter, you will learn how to
- use CLIPS for file I/O of facts.
-
-
- Opening Things Up
-
-
- Before a file can be accessed for reading or writing, it must be opened using
- the open function. The number of files that can be opened at once
- is dependent on your operating system and hardware.
- The general form of the open function is
-
- (call (open "<file-name>" <file-ID> ["<file-access>"]))
-
- As an example,
-
- (call (open "animals.dat" animals "r"))
-
- The open function is called with a call function because you really want the
- side-effect of opening a file rather than the value returned
- by the open function.
- The first argument of open, "<file-name>", is the name of the file on your
- computer. Generally, this will be the physical file name unless
- you've re-assigned the name using an operating system command. For the
- example shown, the file-name is animals.dat.
- The second argument, <file-ID>, is the logical name under which CLIPS knows
- the file. Although the logical could be the same as the file-name,
- you may want to rename it. For example, if the file-name is animals.dat, you
- may want to rename it without the period so that you don't have
- to keep typing double quotes around the name everywhere you use it in CLIPS.
- So you might rename animals.dat as animals or by a different name
- such as data, my-data, input, or any other valid name.
- Another advantage of a logical name is that you can easily substitute a
- different file-name without making major changes in the program.
- For example, you may want to read data from animals.dat for awhile and then
- read data from a file called birds.txt. Only the open statement
- need be changed to accomplish this.
- The third argument, "<file-access>", is optional as indicated by the square
- brackets around it. The four possible modes of file-access are
-
- Mode Action
- r read access only
- w write access only
- r+ read and write access
- a append access only
-
- The default value of file-access is "r".
- As an example of the open function,
-
- (call (open "animals.dat" data "r"))
- will open a file called "animals.dat" and assign it the logical name data.
- Since the file-mode is "r", an alternative statement is
-
- (call (open "animals.dat" data))
-
- Either version of the open statement can be used.
-
-
- $$$And Closing Them Down
-
-
- Once you no longer need to access a file, you should close it down. Unless a
- file is closed, there is no guarantee that the information written
- to it will be saved.
- Although you can open a file when the first rule fires and close it when the
- last rule fires, you're taking an unneccesary risk if you don't
- need to access the data all the time. There may be a power outage or hardware
- failure that prevents the file from closing and so the data you've
- written to it may be lost. The disadvantage of opening and closing files in a
- rule is that execution is slower.
- The general form of the close function is
-
- (call (close [<file-ID>]))
-
- where the optional argument specifies the file to be closed. So
-
- (call (close data))
-
- will close the file known to CLIPS by the logical file-name animals. The
- statements
-
- (call (close input))
- (call (close output))
-
- will close the logical files named input and output. Note that separate
- statements are necessary to close specific files.
- The default case in which no file-ID is specified
-
- (call (close))
-
- will close all open files.
- Let's try an example now of opening and closing files. First, we need to
- create the files to be accessed. Create one file called "animals.dat"
- with the data shown below.
-
- duck goose ganders
- geese
- ducks
-
- Now make a file called "vegtable.dat". You don't have to put any data in this
- file. Notice that the filename is limited to eight characters
- because of limitations on MSDOS filenames. Of course, you can also use any
- filenames that are valid on the system you are using. Just modify
- the names in the following program to open and close the appropriate files.
-
- (defrule read-file
- (initial-fact)
- =>
- (printout "Call 1" crlf)
- (call (open "animals.dat" data1 ))
- (printout "Call 2" crlf)
- (call (open "vegtable.dat" data2))
- (printout "Call close" crlf)
- (call (close))
- (printout "Files closed" crlf))
-
- When you run this program, CLIPS will print the appropriate messages as it
- opens and closes files.
-
-
- A Graceful Exit
-
-
- Although the previous program did nothing but open and close files, it was
- important to remind you of the necessity to have both an open and
- close statement. Before you write practical programs that read and write to
- files, you should be very aware of these requirements. In particular,
- if you do not issue a command to close a file, the data you have written to it
- may be lost.
- CLIPS will not prompt you to close an open file. The only safeguard built
- into CLIPS for closing files that have been inadvertantly left
- open is when you issue an (exit) command. CLIPS will close all open files
- when an (exit) is issued.
- However, a problem arises if you terminate CLIPS with an interrupt control
- character such as Control C or the appropriate interrupt for your
- computer. Depending on your operating system, the data you have written to
- open files may not be saved. That's why it's always a good idea
- to exit CLIPS with an (exit) rather than an interrupt. A graceful exit will
- save any data in files inadvertantly left open.
-
-
- Well, Read My File
-
-
- Let's take a look now at reading data from a file. The function to read data
- from a file is the familiar (read). The only new thing that you
- have to do is specify the opened file to read from as the argument of (read).
- The following program shows how you can read data from a file.
-
- (defrule read-file
- (initial-fact)
- =>
- (printout "Name of file to read ? " crlf)
- (bind ?name (read))
- (call (open ?name data))
- (bind ?input (read data))
- (printout "Data read from file " ?name " is " ?input crlf)
- (assert (data ?input))
- (call (close))
- (printout "File " ?name " is closed" crlf))
-
- This program shows a general way to read from a file. Instead of
- hard-coding the file name into the program, you can bind the name of the
- file to be opened. Also, notice that the default form of open is used because
- the file is opened for reading only.
- Run the program to read data from the "animals.dat" file. Be sure to input
- the double quotes around "animals.dat" since CLIPS will not accept
- the period as part of a valid name.
- The output from the program will be the first atom stored in the file, duck.
- Just as in inputting data from a keyboard, CLIPS will read one
- atom at a time. Since a space or carriage return acts as the terminator of an
- atom, the (read data) will stop reading after the first atom,
- duck, is read.
-
-
- Give Me More
-
-
- In order to read more than one atom, you need to set up a loop. This loop can
- be written by having one rule trigger another. Another way is
- to use a while-loop.
- However, before multiple values can be read in by a loop, a very important
- question needs to be addressed. The important question is how
- do you stop the loop? The loop should not try to read past the end of file or
- the operating system will issue an error message. In order to
- prevent this, CLIPS returns a EOF symbolic atom if you try to read past the
- end of file.
- The following program illustrates one way of reading in multiple values from
- a file.
-
- (defrule read-file
- (initial-fact)
- =>
- (printout "Name of file to read ? " crlf)
- (bind ?name (read))
- (call (open ?name data))
- (bind ?input (read data))
- (while (!(eq ?input EOF))
- (printout ?input crlf)
- (bind ?input (read data)))
- (call (close))
- (printout "*** File " ?name " is closed ***" crlf))
-
- Enter and run this program on the file "animals.dat". You'll see that it does
- read and printout all the data in the file.
-
-
- Printing To Files
-
-
- Besides reading from files, CLIPS allows printing to files with the fprintout
- function. The first argument of (fprintout) is the logical filename.
- Following this is the data to be printed to the file. The following program
- shows an example of printing to a file.
-
- (defrule print-to-file
- (initial-fact)
- =>
- (printout "Name of file to print to ? " crlf)
- (bind ?name (read))
- (call (open ?name data "w"))
- (printout crlf "*** Enter data to file " ?name
- crlf " Use EOF to stop input ***" crlf)
- (bind ?input (read))
- (while (!(eq ?input EOF))
- (fprintout data ?input crlf)
- (bind ?input (read)))
- (call (close))
- (printout "*** File " ?name " is closed ***" crlf))
-
- Unlike (read), which reads only one atom at a time, you can use (fprintout)
- with as many atoms as you want. For example,
-
- (fprintout data "This is being printed to a file" ?input crlf)
-
- will print all the atoms after data to the file.
-
-
- A Standard Change
-
-
- If the first argument of (fprintout) is the special logical filename "t", then
- output will be sent to the standard output device. For example,
- in the previous program, change the (fprintout) action in the while-loop to
-
- (fprintout t ?input crlf)
-
- and run again.
- Instead of printing to a file, the output will go to the standard output
- device. Usually, the standard output device will be the terminal
- screen and so you'll see the output of the (fprintout) on your screen.
- However, depending on your operating system, you may be able to issue
- an operating system command to change the standard output to another device
- such as a printer or modem port. In that case, the output of (fprintout)
- will go to your printer or modem.
- The (read) function also has a "t" option so that you can read from the
- standard input device. Normally, the standard input device is the
- keyboard, but your operating system may allow the standard input to be
- redefined just like the standard output. For example, you may be able
- to redefine the standard input as a modem port or lightpen port.
-
-
-