Sometimes it is convenient in a Fortran program to use files for accessing or storing data - especially when large amounts of data are involved. Too much keyboard input during the run of a program leads to mistakes and tedium, while too much screen output has similar consequences. Putting data into files - both for input and output - is a more leisurely and less error-prone approach.
open (unit = number, file = "name") .
In place of number you insert a positive integer (but not 6) to be used to refer to the file, and instead of name you insert the name of the file. Here are examples of open commands:
open (unit = 2, file = "scores") open (unit = 7, file = "a:scores.txt") open (unit = 5, file = "h:\\results\\primes") open (unit = 24, file = "c:\\fortran\\data\\divisors.dat")
Fortran uses the unit number to access the file with later read and write statements. Several files can be open at once, but each must have a different number. There is one thing to remember about numbering a file - you cannot use the number 6, as GNU Fortran reserves that number to refer to the screen.
Note that quotes enclose the filename. Also, in specifying a directory path for a file, you must use double backslashes instead of single ones. Do not put a space on either side of the colon after the drive letter. If you do not specify a drive or directory path for a file, or if you specify the same drive upon which GNU Fortran is installed but without a path, GNU Fortran will by default assume the file is located on the same drive and in the same directory from where Fortran is running.
If the named file does not already exist, Fortran will create it; if it does exist, Fortran will replace it. (So don't mistakenly give the file the same name as another important file!)
close (5) close (1, 3, 8)The first of these commands closes the file numbered 5, while the second closes the three files numbered 1, 3, and 8. It is not necessary to close files; all files will automatically be closed when an end or stop statement is executed. However, in programs handling large amounts of data it can be prudent to close files before the end of the program in order to avoid possible memory problems and to increase efficiency.
write (7,*)works like a print * command, except that data is written to the file numbered 7 instead of to the screen. The two statements
print *, "The solutions to the equation are : ", x1, x2 write (7,*) "The solutions to the equation are : ", x1, x2
produce exactly the same output, except that the first writes to the screen and the second to file number 7. The command "write (7,*)" on a line by itself serves as a line feed, skipping a line in the file numbered 7 before the next writing to that file.
You can also use write statements in conjunction with format statements to write to a file; this gives you better control of formatting. In the following, the first number in "write (7,5)" refers to the file number and the second to the label of the format statement:
write (7,5) "The solutions are ", x1, " and ", x2 5 format (a,f16.10,a,f16.10)
The "write (7,5)" command works exactly like the similar command "write (*,5)", except that in the former output is directed to file number 7, and in the latter to the screen.
Each execution of a write command writes to a single line in a file. The next write command will write to a new line.
Here is a program that finds and prints to a file the divisors of an integer n :
program divisors c This program finds the divisors of an integer input by the user. c The divisors are printed to a file. integer n, k, d(10) open (unit = 1, file = "divisors") print *, "Enter a positive integer :" read *, n write (1,*) "Here are the divisors of ", n, " :" k = 0 do i = 1, n if (mod(n,i) .eq. 0) then k = k + 1 d(k) = i end if if (k .eq. 10) then write (1,5) (d(j), j = 1, 10) k = 0 end if end do write (1,5) (d(j), j = 1, k) 5 format (10i7) close (1) print *, "The divisors are listed in the file 'divisors'. Bye." end
Note that the program counts the divisors, storing them in an array d, until 10 are accumulated; then it prints these 10 on a single line, reserving 7 places for each divisor. It then begins a new count and repeats the procedure until all divisors are found. The last write statement prints whatever divisors are left over after the last full line of 10. The close statement, included here for demonstration only, is unnecessary, as the program is all but finished at that point and the end statement will automatically close the file anyway.
Suppose for example that a file is numbered 7, and that the first two lines of the file contain the data (separated by commas)
|1.23 , 4.56 , 7.89|
|11, 13 , "Sally"|
If the first two read statements in the program are
read (7,*) x, y, z read (7,*) m, n, firstthen the program assigns x = 1.23, y = 4.56, z = 7.89, m = 11, n = 13, first = "Sally". The variables will have to be declared in the program to correspond with the data assigned them by the read statements. For instance, in the above situation x, y, and z will have been declared real variables, m and n integers, and "first" a character variable. Failure to match variable types with data types will most likely lead to error messages.
It is possible that a program does not know beforehand the length of a file. If data is being read from a loop, there is a way to exit the loop when all data in the file has been read, thereby avoiding a program hang-up. One simply modifies the read statement to something like
read (7,*,end=10)This command instructs Fortran to read the next line in the file numbered 7, but to jump to the statement labelled 10 in the program in the event that the last line in that file has already been read.
You can also use format specifiers in read statements, but this can be somewhat tedious and we will not go into the details. As but one example, suppose you want to make the assignments
n = 77 , x = 123.45 , y = 67.8 ,
where n is an integer and x and y are real variables. Then you may use the read and format statements
read (7,5) n, x, y 5 format (i2,f5.2,f3.1)
and in file number 7 place the corresponding line of data
Fortran will read and separate the data, insert appropriate decimal points, and assign it to the variables. But as you can see the method is confusing and perhaps not worth the effort.