home *** CD-ROM | disk | FTP | other *** search
-
-
-
- Chapter 11
- FILE INPUT/OUTPUT
-
- FILES HANDLE SERIAL DATA
- _________________________________________________________________
-
- One of the most common operations when using a computer is to
- either read from, or write to a file. You are already somewhat
- experienced in file handling from the last chapter, because in
- computer terminology, the keyboard, terminal, and printer are all
- classified as files. A file is any serial input or output device
- that the computer has access to. Since it is serial, only one
- piece of information is available to the computer at any instant
- of time. This is in contrast to an array, for example, in which all
- elements of the array are stored internally and are all available
- at any time.
-
-
- A SHORT HISTORY LESSON
- _________________________________________________________________
-
- Several years ago computers were all large cumbersome machines with
- large peripheral devices such as magnetic tape drives, punch card
- readers, paper tape readers or punches, etc. It was a simple task
- to assign the paper tape reader a symbol and use that symbol
- whenever it was necessary to read a paper tape. There was never
- more than one file on the paper tape being read, so it was simply
- read sequentially, and hopefully the data was the desired data.
- With the advent of floppy disks, and hard disks, it became
- practical to put several files of data on one disk, none of which
- necessarily had anything to do with any of the other files on that
- disk. This led to the problem of reading the proper file from the
- disk, not just reading the disk.
-
- Pascal was originally released in 1971, before the introduction of
- the compact floppy disk. The original release of Pascal had no
- provision for selecting a certain file from among the many included
- on the disk. Each compiler writer had to overcome this deficiency
- and he did so by defining an extension to the standard Pascal
- system. Unfortunately, all of the extensions were not the same,
- and there are now several ways to accomplish this operation. There
- are primarily two ways, one using the Assign statement, and the
- other using the Open statement. They are similar to each other and
- they accomplish the same end result.
-
-
- BACK TO THE PRESENT TIME
- _________________________________________________________________
-
- All of the above was described to let you know that we will have
- a problem in this chapter, namely, how do we cover all of the
- possible implementations of Pascal available? The answer is, we
- can't. Most of what is covered in this chapter will apply to all
-
- Page 11-1
-
- Chapter 11 - File Input/Output
-
- compilers, and all that is covered will apply to the TURBO Pascal
- compilers. As we have mentioned before, this tutorial is
- especially written for the TURBO Pascal compilers, but you should
- be warned that you will find differences in Pascal implementations
- if you have occasion to use a different Pascal compiler someday.
- You may, for example, need to use a mini-computer or a mainframe
- computer someday to complete a programming assignment. When that
- happens, you will find that the area of input/output control will
- probably be the biggest difference in the implementations of
- Pascal.
-
-
- READING AND DISPLAYING A FILE
- _________________________________________________________________
-
- Examine the file READFILE.PAS for an example of ================
- a program that can read a text file from the READFILE.PAS
- disk. In fact, it will read itself from the ================
- disk and display itself on the video monitor.
- The first statement in the program is the Assign
- statement. This is TURBO Pascal's way of selecting which file on
- the disk will be either read from or written to. In this case we
- will read from the disk. The first argument in the Assign
- statement is the device specifier similar to Lst used in the last
- chapter for the printer. We have chosen to use the name Turkey for
- the device identifier, but could have used any valid identifier.
- This identifier must be defined in a var declaration as a text type
- variable as illustrated in line 4. The next argument is the
- filename desired. The filename can be defined as a string
- constant, as it is here, or as a string variable.
-
- The text type is a predefined type and is used to define a file
- identifier. It is predefined as a "file of char", so it can only
- be used for a text file. We will see later that there is another
- type of file, a binary file.
-
- You will find that the operating system that you are using requires
- a file name to follow certain conventions when it is named, and the
- Pascal programming language has a set of rules by which an
- identifier can be named. Since these two conventions are not
- necessarily the same, it is necessary to give each file an external
- name which the operating system is happy with, and an internal
- filename which Pascal is happy with. It now becomes necessary to
- tie these two names together, and this is the primary job of the
- Assign statement.
-
- Now that we have a file identified, it is necessary to prepare it
- for reading by executing a reset statement in line 9. The Reset
- statement positions the read pointer at the beginning of the file,
- ready to read the first piece of information in the file. Once we
- have done that, data is read from the file in the same manner as
- it was when reading from the keyboard. In this program, the input
- is controlled by the while loop which is executed until we exhaust
- the data in the file.
-
- Page 11-2
-
- Chapter 11 - File Input/Output
-
- WHAT ARE THE "EOF" AND "EOLN" FUNCTIONS?
- _________________________________________________________________
-
- The Eof function is new and must therefore be defined. When we
- read data from the file, we move closer and closer to the end of
- the file, until finally we reach the end and there is no more data
- to read. This is called "end of file" and is abbreviated Eof.
- Pascal has this function available as a part of the standard
- library which returns FALSE until we reach the last line of the
- file. When there is no more data to read left in the file, the
- function Eof returns TRUE. To use the function, we merely give it
- our file identifier as an argument. It should be clear to you that
- we will loop in this program until we read all of the data
- available in the input file.
-
- The Eoln function is not used in this program but is a very useful
- function. If the input pointer is anywhere in the text file except
- at the end of a line, the Eoln returns FALSE, but at the end of a
- line, it returns a value of TRUE. This function can therefore be
- used to find the end of a line of text for variable length text
- input.
-
- To actually read the data, we use the Readln procedure, giving it
- our identifier Turkey and the name of the variable we want the data
- read into. In this case, we read up to 80 characters into the
- string and if more are available, ignore them. You should remember
- when we did this in the last chapter from the keyboard input. We
- are using the same technique here except we are reading from a file
- this time. Since we would like to do something with the data, we
- output the line to the default device, the video monitor. It
- should be clear to you by now that the program will read the entire
- file and display it on the monitor.
-
- Finally, we Close the file Turkey. It is not really necessary to
- close the file because the system will close it for us
- automatically at program termination, but it is a good habit to get
- into. It must be carefully pointed out here, that you did not do
- anything to the input file, you only read the data and left it
- intact. You could Reset it and reread it again in this same
- program. Compile and run this program to see if it does what you
- expect it to do.
-
-
- A PROGRAM TO READ ANY FILE
- _________________________________________________________________
-
- Examine the next program READDISP.PAS for an ================
- improved file reading program. This is very READDISP.PAS
- similar to the previous program, except that it ================
- asks you for the name of the file which you wish
- to display. After you enter the filename, it
- enters the name into a 12 character string which is named
- Name_Of_File_To_Input which will be the external filename. This
- is then used in the Assign statement to select the file to be read,
-
- Page 11-3
-
- Chapter 11 - File Input/Output
-
- and to connect the external filename to the internal filename,
- Chicken. The file is then reset as before. Lines 15 through 18
- display a header, and from that point on, the program is identical
- to the last one with a few small additions. In order to
- demonstrate the use of a function within the Writeln specification,
- the program calls for the length of the input string in line 23 and
- displays it before each line. The lines are counted as they are
- read and displayed, and the line count is displayed at the end of
- the listing. Both of these operations are done only to illustrate
- to you how they can be done.
-
- You should be able to understand clearly how each of these
- operations is accomplished. Compile and run this program, entering
- any filename we have used so far as the file to be listed on the
- monitor (be sure to include the .PAS extension). After a
- successful run, enter a nonexistent filename and see the I/O error
- generated by the Pascal runtime system. The next example program
- will illustrate a more graceful method of detecting this error.
-
-
- HOW TO COPY A FILE (SORT OF)
- _________________________________________________________________
-
- Examine the file READSTOR.PAS for an example of ================
- reading from a file and writing to another one. READSTOR.PAS
- In this program we request an operator input for ================
- the filename to read, after which we Assign the
- name to the file and Reset it. When we reset
- the file however, we go to a bit of extra trouble to assure that
- the file actually exists. Note that this is an extension to TURBO
- Pascal and will probably not work with other Pascal compilers.
-
- Suppose we input a filename, and the file did not exist because the
- file was actually missing, or because we entered the name of the
- file wrong. Without this extra effort, the TURBO Pascal runtime
- system would indicate a run-time error, and terminate the program
- returning us to the operating system. In order to make a program
- easier to use, it would be nice to tell the operator that the file
- didn't exist and give him the opportunity to try again with another
- file name. The method given in lines 16 through 20 of this program
- will allow you to do just that.
-
-
- USING A COMPILER DIRECTIVE
- _________________________________________________________________
-
- First you must disable the built in TURBO Pascal I/O checking by
- inserting the compiler directive in line 16. This tells the system
- to ignore any I/O errors from this point on and if the file doesn't
- exist, the system will not abort when you attempt to reset it in
- line 17. Another compiler directive is given in line 18 to enable
- I/O checking again for the remainder of the program.
-
-
-
- Page 11-4
-
- Chapter 11 - File Input/Output
-
-
- WE DO OUR OWN FILE CHECKING
- _________________________________________________________________
-
- If the file didn't exist and could not therefore be reset, we have
- a problem because the program thinks the file is available for use
- but it actually isn't. Fortunately, TURBO Pascal has a built in
- variable, named IOResult that informs us of the result of each I/O
- operation. Following any I/O operation, if this variable contains
- the value of zero, the I/O operation was correct, and if it
- contains any other value, the operation had some sort of error.
- In our case, we simply compare it to zero to generate a boolean
- value, then based on the boolean value we either give an error
- message and stop, or perform the desired file operations.
-
- It would be good programming practice to check all file openings
- in this manner to allow the operator to recover from a simple
- oversight or spelling error.
-
- If the file was opened properly, then in line 21 through 24 we
- request a different filename to write to, which is assigned to a
- different identifier. Note that the output file is not checked for
- a valid opening in this example as it should be. The statement in
- line 24 is new to us, the Rewrite statement. This name apparently
- comes from the words REset for WRITEing because that is exactly
- what it does. It clears the entire file of any prior data and
- prepares to write into the very beginning of the file. Each time
- you write into it, the file grows by the amount of the new data
- written.
-
- Once the identifier has been defined, and the Rewrite has been
- executed, writing to the file is identical to writing to the
- display with the addition of the identifier being specified prior
- to the first output field. With that in mind, you should have no
- trouble comprehending the operation of the program. This program
- is very similar to the last, except that it numbers the lines as
- the file is copied. After running the program, look in your
- default directory for the new filename which you input when the
- system asked for the output filename. Examine that file to see if
- it is truly a copy of the input file with line numbers added.
-
- Actually a much better style would result if the logic for each
- file opening was put into a procedure of its own. In addition to
- this being easier to debug and understand, the completed procedures
- could be reused in other programs in the future.
-
- One word of caution. If you used an existing filename for the
- output file, the file was overwritten, and the original destroyed.
- In that case, it was good that you followed instructions at the
- beginning of this tutorial and made a working copy of the
- distribution disk. You did do that, didn't you?
-
- Compile and run this program two different ways, once with a valid
- input filename that should run properly, and the second time with
-
- Page 11-5
-
- Chapter 11 - File Input/Output
-
- an input filename that doesn't exist to prove to yourself that the
- test actually does work correctly.
-
-
- HOW TO READ INTEGER DATA FROM A FILE
- _________________________________________________________________
-
- It is well and good to be able to read text from a file, but now
- we would like to read other forms of data from a file. First we
- will look at an example program to read data from a text file, then
- later we will see an example program that reads from a binary file.
-
- Examine the program READINTS.PAS for an example ================
- of reading data from a text file. A text file READINTS.PAS
- is an ASCII file that can be read by a text ================
- editor, printed, displayed, or in some cases,
- compiled and executed. It is simply a file made
- up of a long string of char type data, and usually includes
- linefeeds, carriage returns, and blanks for neat formatting.
- Nearly every file on the Tutorial disk you received with this
- package is a text file. One notable exception is the file named
- LIST.EXE, which is an executable program file.
-
- The example program has nothing new, you have seen everything in
- it before. We have an assignment, followed by a reset of our file,
- followed by four read and write loops. Each of the loops has a
- subtle difference to illustrate the Read and Readln statements.
- Notice that the same file is used for reading four times with a
- Reset prior to each, illustrating the nondestructive read mentioned
- a few paragraphs ago.
-
- The file we will be using is named INTDATA.TXT and is on your disk.
- You could display it at this time using the program READDISP.PAS
- we covered recently. Notice that it is simply composed of the
- integer values from 101 to 148 arranged four to a line with a
- couple of spaces between each for separation and a neat appearance.
- The important thing to remember is that there are four data points
- per line.
-
-
- READ AND READLN ARE SLIGHTLY DIFFERENT
- _________________________________________________________________
-
- As variables are read in with either procedure, the input file is
- scanned for the variables using blanks as delimiters. If there are
- not enough data points on one line to satisfy the arguments in the
- input list, the next line is searched also, and the next, etc.
- Finally when all of the arguments in the input list are satisfied,
- the Read is complete, but the Readln is not. If it is a Read
- procedure, the input pointer is left at that point in the file, but
- if it is a Readln procedure, the input pointer is advanced to the
- beginning of the next line. The next paragraph should clear that
- up for you.
-
-
- Page 11-6
-
- Chapter 11 - File Input/Output
-
- The input data file INTDATA.TXT has four data points per line but
- the first loop in the program READINTS.PAS requests only three each
- time through the loop. The first time through, it reads the values
- 101, 102, and 103, and displays those values, leaving the input
- pointer just prior to the 104, because it is a Read procedure. The
- next time through, it reads the value 104, advances to the next
- line and reads the values 105, and 106, leaving the pointer just
- prior to the 107. This continues until the 5 passes through the
- loop are completed.
-
- The loop in lines 19 through 22 contains a Readln procedure and
- also reads the values 101, 102, and 103, but when the input
- parameter list is satisfied, it moves the pointer to the beginning
- of the next line, leaving it just before the 105. The values are
- printed out and the next time we come to the Readln, we read the
- 105, 106, and 107, and the pointer is moved to the beginning of the
- next line. It would be good to run the program now to see the
- difference in output data for the two loops. Remember that the
- only difference is that the first loop uses the Read procedure, and
- the second uses the Readln procedure.
-
- When you come back to the program again, observe the last two
- loops, which operate much like the first two except that there are
- now five requested integer variables, and the input file still only
- has four per line. This is no problem. Both input procedures will
- simply read the first four in the first line, advance to the second
- line for its required fifth input, and each will do its own
- operation next. The Read procedure will leave the input pointer
- just before the second data point of the second line, and the
- Readln will advance the input pointer to the beginning of the third
- line. Compile and run this program and observe the four output
- fields to see an illustration of these principles.
-
-
- NOW TO READ SOME REAL VARIABLES FROM A FILE
- _________________________________________________________________
-
- Examine the file named REALDATA.TXT supplied on your Pascal
- Tutorial disk. You will see 8 lines of what appears to be
- scrambled data, but it is good data that Pascal can read. Notice
- especially line 4 which has some data missing, and line 6 which has
- some extra data.
-
- Examine the program file READDATA.PAS which will ================
- be used to illustrate the method of reading real READDATA.PAS
- type data. Everything should be familiar to ================
- you, since there is nothing new here. The
- Readln statement is requesting one integer
- variable, and three real variables, which is what most of the input
- file contains. When we come to the fourth line, there are not
- enough data points available, so the first two data points of the
- next line are read to complete the fourth pass through the loop.
- Since the file pointer is advanced to the beginning of the next
- line, we are automatically synchronized with the data again. When
-
- Page 11-7
-
- Chapter 11 - File Input/Output
-
- we come to the sixth line, the last two data points are simply
- ignored. Run the program to see if the results are as you would
- predict.
-
- If a Read were substituted for the Readln in line 14 of the
- program, the file pointer would not be advanced to the beginning
- of line 6 after the fourth pass through the loop. The next attempt
- to read would result in trying to read the value 0.0006 as an
- integer, and a run time error would result. Modify the program,
- substituting a Read for the Readln in line 14, and see if this is
- not true. It will be left as an exercise for the diligent student
- to add code to detect and act on the error in a manner similar to
- that illustrated in READSTOR.PAS earlier in this chapter.
-
- It should be pointed out that TURBO Pascal requires a digit both
- before and after the decimal point in all data that is to be read
- in as real type data or it will be flagged as a run-time error and
- the program will be halted. The digits can be zero as they are in
- several places in the example file but they must be there.
-
- That is all there is to reading and writing text files. If you
- learn the necessities, you will not be stumbling around in the area
- of input/output which is very intimidating to many people.
- Remember to Assign, then Reset before reading, Rewrite before
- writing, and Close before quitting. It is of the utmost importance
- to close a file you have been writing to before quitting to write
- the last few buffers to the file, but it is not as important to
- close read files unless you are using a lot of them, as there is
- an implementation dependent limit of how many files can be open at
- once. It is possible to read from a file, close it, reopen it, and
- write to it in one program. You can reuse a file as often as you
- desire in a program, but you cannot read from and write into a file
- at the same time.
-
-
-
- NOW FOR BINARY INPUT AND OUTPUT
- _________________________________________________________________
-
- Examine the file BINOUT.PAS for an example of ================
- writing data to a file in binary form. First BINOUT.PAS
- there is a record defined in the type ================
- declaration part composed of three different
- variable types. In the var part, Output_File is
- defined as a "file of Dat_Rec", the record defined earlier. The
- variable Dog_Food is then defined as an array of the record, and
- a simple variable is defined.
-
- Any file assigned a type of text, which is a "file of char", is a
- text file. A text file can be read and modified with a text
- editor, printed out, displayed on the monitor, etc. If a file is
- defined with any other definition, it will be a binary file and
- will be in an internal format as defined by the Pascal compiler and
- may not be readable by any compiler other than the one used to
-
- Page 11-8
-
- Chapter 11 - File Input/Output
-
- write it. Attempting to display such a file will result in very
- strange looking gibberish on the monitor.
-
- When we get to the program, the output file is assigned a name in
- line 15, and a Rewrite is performed on it to reset the input
- pointer to the beginning of the file, empty the file, and prepare
- for writing data into it. The loop in lines 18 through 22 simply
- assigns nonsense data to all of the variables in the 20 records so
- we have something to work with.
-
- We write a message to the display that we are ready to start
- outputting data, then we output the data one record at a time with
- the standard Write statement. A few cautions are in order here.
- The output file can be defined to store any simple variable type,
- integer, byte, real, or a record, but the types cannot be mixed.
- The record itself however, can be any combination of data including
- other records if desired, but any file can only have one type of
- record written to it.
-
- A Writeln statement is illegal when writing to a binary file
- because a binary file is not line oriented. A Write statement is
- limited to one output field per statement. This is not a serious
- limitation since it is a simple matter to put one Write statement
- in the program for each variable you wish to write out to the file.
- It is important to Close the file when you are finished writing to
- it.
-
-
- WHY USE A BINARY FILE
- _________________________________________________________________
-
- A binary file written by a Pascal program cannot be read by a word
- processor, a text editor or any other application program such as
- a database or spreadsheet, and it may not even be readable by a
- Pascal program compiled by a different companies compiler because
- the actual data structure is implementation dependent. It can't
- even be read by a Pascal program using the same compiler unless the
- data structure is identical to the one used to write the file.
- With all these rules, it seems like a silly way to output data, but
- there are advantages to using a binary output.
-
- A binary file uses less file space than a corresponding text file
- because the data is stored in a packed mode. Since all significant
- digits of real data are stored, it is more precise unless you are
- careful to output all significant data to the corresponding text
- file. Finally, since the binary data does not require formatting
- into ASCII characters, it will be considerably faster than
- outputting it in text format. When you run this example program,
- it will create the file KIBBLES.BIT, and put 20 records in it.
- Return to DOS and look for this file and verify its existence. If
- you try to TYPE it, using the DOS TYPE command, you will have a
- real mess on your monitor because it does not contain char type
- data, but that might be a good exercise.
-
-
- Page 11-9
-
- Chapter 11 - File Input/Output
-
- READING A BINARY FILE
- _________________________________________________________________
-
- BININ.PAS is another example program that will ===============
- read in the file we just created. Notice that BININ.PAS
- the variables are named differently, but the ===============
- types are all identical to those used to write
- the file and they are in the same order. An
- additional line is found in the program, the if statement. We must
- check for the "end of file" marker to stop reading when we find it
- or Pascal will list an error and terminate operation. Three pieces
- of information are written out to verify that we actually did read
- the data file in.
-
- Once again, a few rules are in order. A Readln is illegal since
- there are no lines in a binary file, and only one variable or
- record can be read in with each Read statement.
-
-
- FILE POINTERS, GET, AND PUT STATEMENTS
- _________________________________________________________________
-
- File pointers and the Get and Put procedures are a part of standard
- Pascal, but since they are redundant and therefore not needed, they
- are not a part of TURBO Pascal. The standard Read and Write
- procedures are more flexible, more efficient, and easier to use.
- The use of Get and Put will not be illustrated or defined here.
- If you ever have a need for them, they should be covered in detail
- in your Pascal reference manual for the particular implementation
- you are using.
-
- Pointers will be covered in detail in the next chapter of this
- tutorial.
-
-
- PROGRAMMING EXERCISES
- _________________________________________________________________
-
- 1. Modify READFILE.PAS so that after reading and displaying the
- file, the file is reset, then read and displayed again. This
- was suggested in the text.
-
- 2. Write a program to read the data from any text file, and
- display it on the monitor with line numbers and the number of
- characters in each line. Finally display the number of lines
- found in the file, and the total number of characters in the
- entire file. Compare this number with the filesize given by
- the DOS command DIR.
-
-
-
-
-
-
-
- Page 11-10