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
-
- Page 11-1
-
- File Input/Output
-
- 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 compilers, and all that is covered will
- apply to the TURBO Pascal compilers, versions 3.0 through 5.x.
- This tutorial is especially written for the TURBO Pascal
- compilers, but you should be warned you will find differences
- in Pascal implementations if you ever find a need 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 READFILE.PAS
- file from the disk. In fact it will read ================
- itself from the disk and display it 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.
- 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.
-
- 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.
-
-
- WHAT ARE THE "EOF" AND "EOLN" FUNCTIONS?
- ____________________________________________________________
-
- The Eof function is new and must be defined. When we read
- data from the file, we move closer and closer to the end,
-
- Page 11-2
-
- File Input/Output
-
- 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 you
- 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 it 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 READDISP.PAS
- very similar except that it asks you for ================
- the name of the file that you wish to
- display, and enters the name into a 12
- character string named Name_Of_File_To_Input. This is then
- used in the Assign statement to select the file to be read,
- and the file is 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
-
- Page 11-3
-
- File Input/Output
-
- 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.
-
- You should be able to see clearly how each of these operations
- is accomplished. Compile and run this program, entering any
- filename we have used so far (be sure to include the .PAS
- extension). After a successful run, enter a nonexistent
- filename and see the I/O error.
-
-
- HOW TO COPY A FILE (SORT OF)
- ____________________________________________________________
-
- Examine the file READSTOR.PAS for an ================
- example of reading from a file and writing READSTOR.PAS
- to another one. 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.
-
- Suppose we input a filename, and the file did not exist
- because the file was actually missing, or because we entered
- the filename wrong. Without the 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.
-
-
- 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
-
- Page 11-4
-
- File Input/Output
-
- 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 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 it asked for the output
- filename. Examine that file to see if it is truly a copy of
- the input file with line numbers added.
-
- 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 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
-
- Page 11-5
-
- File Input/Output
-
- 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. READINTS.PAS
- A text file 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.
-
- 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,
-
- Page 11-6
-
- File Input/Output
-
- 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. 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 READDATA.PAS
- method of reading real 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
- contained. 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 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.
-
-
- Page 11-7
-
- File Input/Output
-
- 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 should be pointed out that TURBO Pascal 4.0 and 5.x both
- require 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. If you are using TURBO
- Pascal 3.0, the leading and trailing digits are not required.
-
- 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. BINOUT.PAS
- First 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 write it. Attempting to display
- such a file will result in very strange looking gibberish on
- the monitor.
-
-
- Page 11-8
-
- File Input/Output
-
- 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
-
- File Input/Output
-
- READING A BINARY FILE
- ____________________________________________________________
-
- BININ.PAS is another example program that =================
- will read in the file we just created. BININ.PAS
- Notice that 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 any 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