home *** CD-ROM | disk | FTP | other *** search
-
- CHAPTER 11 - Files
-
-
- 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 compilers, and all that is covered
- will apply to the TURBO Pascal compilers, versions 3.0 and
- 4.0. If you are not using TURBO Pascal and your compiler
- complains about some of the statements, it will be up to you
-
-
- Page 63
-
-
-
-
-
-
-
-
-
- CHAPTER 11 - Files
-
-
- to dig out the details of how to do the intended operations.
- If any one or more of these operations cannot be
- accomplished with your compiler, you should seriously
- consider purchasing a better compiler because all of these
- operations are needed in a useful Pascal environment.
-
- READING AND DISPLAYING A FILE
-
- Examine the file READFILE for an example of a program
- that can read a text 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, 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
-
-
-
- Page 64
-
-
-
-
-
-
-
-
-
- CHAPTER 11 - Files
-
-
- an argument. It should be clear that we will loop 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 for an improved file
- reading program. This is very similar except that it asks
- you for the name of the file that you desire 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 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.
-
-
-
-
- Page 65
-
-
-
-
-
-
-
-
-
- CHAPTER 11 - Files
-
-
- 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 for an example of both
- reading from a file and writing 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 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.
-
-
-
- Page 66
-
-
-
-
-
-
-
-
-
- CHAPTER 11 - Files
-
-
- 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 text file, then later we will see an example
- program that reads from a binary file.
-
- Examine the program READINTS for an example of reading
- data from a text file. A text file is an ASCII file that
-
-
- Page 67
-
-
-
-
-
-
-
-
-
- CHAPTER 11 - Files
-
-
- 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.COM, 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 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, and 106, leaving the pointer just
- prior to the 107. This continues until the 5 passes through
- the loop are completed.
-
-
-
-
- Page 68
-
-
-
-
-
-
-
-
-
- CHAPTER 11 - Files
-
-
- 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
-
- By whatever method you desire, take a look at 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 which will be used to
- illustrate the 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.
-
- 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.
-
-
- Page 69
-
-
-
-
-
-
-
-
-
- CHAPTER 11 - Files
-
-
- 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 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. 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 for an example of writing data
- to a file in binary form. 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. 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
-
-
- Page 70
-
-
-
-
-
-
-
-
-
- CHAPTER 11 - Files
-
-
- 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, and 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 as 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. 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, but that might be a good
- exercise.
-
-
-
- Page 71
-
-
-
-
-
-
-
-
-
- CHAPTER 11 - Files
-
-
- READING A BINARY FILE
-
- BININ is another example program that will read in the
- file we just created. Notice that the variables are named
- differently, but the types are all identical to those used
- to write the file. 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.
-
- WHAT ABOUT 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, 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. Write a program to read in 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.
-
- 2. Write a silly program that will read two text files and
- display them both on the monitor on alternating lines.
- This is the same as "shuffling" the two files together.
- Take care to allow them to end at different times,
- inserting blank lines for the file that terminates
- earlier.
-
-
-
-
-
-
-
- Page 72
-