Generalized I/O
Mystery of stars
• I/O statements took the form
read *, x, y,z
print *, a,b,c
• Such I/O is said to be List-directed or in free format
• user has no control over the appearance of I/O
• No flexibility over the I/O devices
• Keyboard input
• Display unit output
• * indicates no control or default format
Mystery resolved
•
* stands for (*,*)
•
In general, it will be (arg1,arg2)
•
arg1 used to select the I/O device
–
* indicates default devices (keyboard
and monitor)
•
arg2 controls the I/O formatting
–
It is a string constant
– *
means default formatting
Files
•
I/O through files is the most
convenient
•
Standard I/O is very painful for large
data
•
Large amount of data can be stored and
retrieved with ease
•
Output of one program can be used as
input to another
•
The programs need not be running at the
same time
•
Once created they remain - permanent
memory
•
Files are high level software
abstractions of these permanent memory devices
• They
are called as secondary memory
Secondary Memory
•
permanent, slow and large volume of
data
•
Some kind of magnetic memory –
•
no power required to retain unlike main
memory
•
different kinds - Hard Disks, Floppy
Disc, CDs, Magnetic Tapes (old)
•
Random or Sequential access
•
details of devices abstracted from
application programmers
•
Files are the abstractions
• Std.
I/O are also files
File Organization
•
Fortran programmer's view
•
A simple file is a linear sequence of
records
•
Each record is a meaningful piece of
data
•
Files are read or written one record at
a time
•
Each record is typically a line of data
–
creation of file determines type of
data
•
Files can be sequential or random
access
• Random
access files require keys
File Operations
•
Opening a file
•
writing or reading a record
•
Rewinding a file
•
Closing a file
•
Valid sequence
–
(open (read/write/rewind)* close)*
•
File operations translated to OS calls
• They
can fail and graceful recovery possible
File Opening
•
Simplest
example is:
open(unit
= 23, file = "input.dat")
•
This
commands associates the file input.dat with the number 23
•
This
number can be used for reading and writing onto the file
•
Example: read(23, *) N
write(23,
*) M
•
Unit
numbers are system dependent (usually from 1 to 100)
•
unit
and file are named parameters
• Contrast this with
positional parameters
Open attributes
•
Many
file attributes assume default values in the above
•
to
override these, additional parameters to be set
•
action
= READ, WRITE or READWRITE (default)
•
status
= OLD, NEW, REPLACE (default), SCRATCH, UNKNOWN
•
ios
= x, x is assigned a value at the end
of the call
0 - if the operation is successful
> 0 - otherwise
• access =
"sequential" (default) or "direct"
Some more attributes
•
form
= "formatted" (default) or
"unformatted“
–
in unformatted form, data stored in
some internal representation
–
can not be edited
•
recl
= length of each record
–
required for direct access files
• position =
"rewind", "append"
Example
integer::
ierr
open(unit=23,
file = "in.dat", status = "old",
action = "Read“,
iostat = ierr)
–
opening the existing file "in.dat",
for read
–
ierr gets a value > 0 iff failure in
opening
Another Example
integer::
ierr
integer::
ut = 34
open(unit=
ut, file = "out.dat", status = "new",
action = "write“, iostat = ierr)
–
creating a new file "out.dat
–
Status = replace would replace the file
One more Example
open(unit=
15, status = "scratch", iostat = ierr)
–
no file name specified - error
otherwise
–
default action - reading and writing
temporary data
– erased
after the program terminates
Closing a file
• Close(close_list)
•
Close_list
–
must specify the unit number
–
may specify other clauses
•
the number is released and can be
reused in other open statements
•
repeated opening and closing of non
scratch files possible
• scratch
file contents lost once they are closed
Reading and Writing
•
files
contain sequence of records
•
Each
record is read/written using a single read or write operation
•
So
we can say that each record occupies a single line
•
Every
read statement refers to the successive records
•
Reference
to the file through the unit number
•
example:
read(unit
= 16, *) x, y, z
write(unit
= 25, *) "test output=", a, b, c
• read and write one
record to the appropriate file
Read Pointer
•
There
can be errors while reading a file
•
There
is a read pointer that indicates the next record to be read
•
Every
read moves the read pointer to the next record (in sequential access)
Read Error
•
The read pointer may be at
the end
•
use istat clause for
detecting end of file (EOF)
Read(16,*, iostat = err) x, y, z
•
If err is non zero then
there is an error
•
Use always iostat clause
• otherwise, program will abort
Other parameters
•
For direct access files, use the argument
rec = n
•
This reads/writes the nth record
Example:
write(23,*,iostat =
err, rec = 15) i,j
– write
values of i, j to the record 15 of the associated file
Program bubble_sort
implicit
none
integer:: N, i, rt_end, index,
temp
! N - the total number of items in
the array
! i, j - array index variables
integer, dimension(100):: A
integer:: err,errf, werr
open(unit=1, file =
"in.dat", &
status =
"old", iostat = err)
if (err/=0) then
print *, "file opening
error"
else
outer: do
Program Continued
read (unit =1, iostat = errf,
fmt = * ) N
read (1, *, iostat = errf) (A(i),i=1,N)
if (errf /= 0) exit
rt_end = N
inner: do
if (rt_end <= 1) exit
index = 0
do i = 1, (rt_end-1)
if (A(i) > A(i+1))
then
temp = A(i)
A(i) = A(i+1)
A(i+1) = temp
index = i
endif
enddo
rt_end = index
end do inner
Program Continued
open(unit=2, file =
"out.dat", &
status = "old", access
= "sequential", &
iostat = werr)
print *, (A(i),i=1,N)
write (2, fmt = *) (A(i),i=1,N)
end do outer
endif
close(unit=1)
end
program
I/O Formatting
•
So
far we have used List-Directed I/O Statements (Free format)
print
*, A,B,C
read
*, A,B
•
Fine
for small programs and small number of inputs and outputs
•
Many
data processing applications manipulate large collection of inputs and outputs
–
Tabulating
marks and results
–
preparing
mark sheets and reservation charts
•
Pretty
printing and Formatted input very essential
• Fortran has elaborate
features for formatting I/O
Format Strings
•
I/O
formats can be specified by using format strings
print
fs, A, B,C
read fs, C,D
•
fs
identifies a format string
–
a
constant string
–
a
string variable
–
a
label that labels a format statement containing the format string
•
Here
is an example format strings
print
"I4, I4, I4", A, B, C
• This prints A, B and
C in a row with each being given 4 decimal places
Edit Descriptor
•
I4
is an edit descriptor
•
Format
string contains one or more edit descriptors
•
Very
many edit descriptors that help print different types of variables
•
Alternate
format strings
Character(len=20)::
str
str = "(I4, I4, I4, I4)”
write(*, str) a,b,c,d
read *, 100, a, b, c, d
100 format ("I4,I4,I4,I4")
print "4I4", a, b,c,d
I/O buffer
• I/O
done through buffers
• Buffer
is a temporary storage space where every line of characters is composed before
doing I/O
• Line-oriented
I/O
• For
reading – input process builds the buffer and gives the buffer content to the
program
• Every
print statement composes the output in the output buffer completely before
sending for printing on the device
• Buffers
are read/written as per the format statement
Output Buffer
• Usually
133 characters long (line-printer output)
• First
character is a control character
–
1 skip to next page
–
Blank single spacing
(default when * is used)
–
0 double spacing
–
+ no space – overwriting
• The
rest of the characters are printed
• Make
sure that first character is the intended control character
print (*,100) n
100 format (I3)
Behaviour of print statement when n = 25 and
n =125
Some descriptors
•
Iw - w columns reserved for printing an
integer value includes - if the number is negative
•
5Iw - 5 successive w columns reserved
for printing/reading 5 values
•
Iw.m - minimum m digits need to be
presented
•
If w not enough then * printed
• If
the number is less than m digits - leading zeros added
Format Descriptors
•
rFw.d
r - repeat count
w - number of columns for the entire
number
(including
decimal point and -ve sign)
d - number of columns to the right
of the decimal point
•
Number appears right-justified
•
Trailing zeros if the no. of digits
after decimal point is less than d
•
rounded off if d is more
• if
(w-d-1) is less, then asterisks printed
E-descriptor
rEw.d
Printing is done in E notation
Print "E11.4", A
will print -0.1234E-02 when the value of A is
1.234 * 10 ** -1
Make sure that
w > = d + 7
A-descriptor
rA
or rAw
if w is more then A is right justifies
if w is less than only first w characters of A are printed
X descriptor
nX inserts n spaces in the output
T descriptor
Tc moves to the column number c
rLw
used for printing logical variables -
w columns are used
output will be either T or F, right
justified
Repetition
Repetition
can be applied to groups of descriptors
2(I6, 2X, 2F10.2)
is used to print/read two groups, each consisting of an integer (6 digits)
and two floating point numbers of size 10
/ operator used for breaking the line
A single write statement can print on more than one line
Descriptor Association
•
print
fs, var_list
•
association
of format descriptor to a variable is done from left to right
•
if
for every descriptor (except print controls) there is a variable and vice
versa, then association is simple
•
if
less variables then rest of the descriptors discarded
•
if
more variables then the printing starts from a fresh line for rest of the
variables
• format strings for
these variables start from right most open parenthesis that does not have
repetition count
Example
print (8, 60) j,k,l,m,n
60 format
(1X,"The value” = , /, (1X, ‘New Line', 2(3X,
I5)))
The
output is
1 16 24 (column number not
printed)
The value =
New Line 1 2
New Line 3 4
New Line 5
where
j - n has the value 1 - 5
Other aspects
•
Formatted reading is similar (see the
books/manuals for details)
•
Format strings can be specified in
generalized file-based I/O
• Include
the format string in the argument fmt