@@ -4,56 +4,98 @@ title: File Input/Output
4
4
permalink : /learn/best_practices/file_io
5
5
---
6
6
7
- To read from a file:
7
+ In Fortran files are managed by unit identifiers. Interaction with the filesystem
8
+ mainly happens through the `` open `` and `` inquire `` built-in procedures.
9
+ Generally, the workflow is to open a file to a unit identifier, read and/or write
10
+ to it and close it again.
8
11
9
- ``` fortran
10
- integer :: u
11
- open(newunit=u , file="log.txt", status="old", action='read' )
12
- read(u, *) a, b
13
- close(u )
12
+ ``` fortran
13
+ integer :: io
14
+ open(newunit=io , file="log.txt")
15
+ ! ...
16
+ close(io )
14
17
```
15
18
16
- Write to a file as follows:
19
+ By default the file will be created if it is not existing already and opened for
20
+ both reading and writing. Writing to an existing file will start in the first
21
+ record (line) and therefore overwrite the file by default.
17
22
18
- ``` fortran
19
- integer :: u
20
- open(newunit=u, file="log.txt", status="replace", action='write')
21
- write(u, *) a, b
22
- close(u)
23
+ To create a read-only access to a file the `` status `` and `` action `` have to be
24
+ specified with
25
+
26
+ ``` fortran
27
+ integer :: io
28
+ open(newunit=io, file="log.txt", status="old", action="read")
29
+ read(io, *) a, b
30
+ close(io)
31
+ ```
32
+
33
+ In case the file is not present a runtime error will occur. To check for the existence
34
+ of a file prior to opening it the `` inquire `` function can be used
35
+
36
+ ``` fortran
37
+ logical :: exists
38
+ inquire(file="log.txt", exist=exists)
39
+ if (exists) then
40
+ ! ...
41
+ end if
23
42
```
24
43
25
- It is possible to append to an existing file as follows :
44
+ Alternatively, the `` open `` procedure can return an optional * iostat * and * iomsg * :
26
45
27
- ``` fortran
28
- integer :: u
29
- open(newunit=u, file="log.txt", position="append", status="old")
30
- write(u, *) N, V(N)
31
- close(u)
46
+ ``` fortran
47
+ integer :: io, stat
48
+ character(len=512) :: msg
49
+ open(newunit=io, file="log.txt", status="old", action="read", &
50
+ iostat=stat, iomsg=msg)
51
+ if (stat /= 0) then
52
+ print *, trim(msg)
53
+ end if
32
54
```
33
55
34
- The ` newunit ` keyword argument to ` open ` is a Fortran 2008 standard feature. Therefore for
35
- older compilers that do not suport it, just replace ` open(newunit=u, ...) ` by:
56
+ Note that * iomsg* requires a fixed-length character variable with sufficent storage
57
+ size to hold the error message.
58
+
59
+ Similarly, writing to a file happens by using the * status* and * action* keyword.
60
+ To create a new file use
36
61
37
- ``` fortran
38
- open(newunit(u), ...)
62
+ ``` fortran
63
+ integer :: io
64
+ open(newunit=io, file="log.txt", status="new", action="write")
65
+ write(io, *) a, b
66
+ close(io)
39
67
```
40
68
41
- where the ` newunit ` function is defined by:
42
-
43
- ``` fortran
44
- integer function newunit(unit) result(n)
45
- ! returns lowest i/o unit number not in use
46
- integer, intent(out), optional :: unit
47
- logical :: inuse
48
- integer, parameter :: nmin=10 ! avoid lower numbers which are sometimes reserved
49
- integer, parameter :: nmax=999 ! may be system-dependent
50
- do n = nmin, nmax
51
- inquire(unit=n, opened=inuse)
52
- if (.not. inuse) then
53
- if (present(unit)) unit=n
54
- return
55
- end if
56
- end do
57
- error stop 'newunit ERROR: available unit not found.'
58
- end function
69
+ Alternatively, `` status="replace" `` can be used to overwrite an existing file,
70
+ it is highly recommended to first check for the existence of a file before deciding
71
+ on the * status* to use.
72
+ To append to an output file the * position* keyword can be specified explicitly with
73
+
74
+ ``` fortran
75
+ integer :: io
76
+ open(newunit=io, file="log.txt", position="append", &
77
+ & status="old", action="write")
78
+ write(io, *) size(v)
79
+ write(io, *) v(:)
80
+ close(io)
59
81
```
82
+
83
+ To reset the position in a file the built-in procedures `` rewind `` and `` backspace ``
84
+ can be used. `` rewind `` will reset to the first record (line), while `` backspace `` will
85
+ return to the previous record (line).
86
+
87
+ Finally, to delete a file the file has to be opened and can be deleted after closing
88
+ with
89
+
90
+ ``` fortran
91
+ logical :: exists
92
+ integer :: io, stat
93
+ inquire(file="log.txt", exist=exists)
94
+ if (exists) then
95
+ open(file="log.txt", newunit=io, iostat=stat)
96
+ if (stat == 0) close(io, status="delete", iostat=stat)
97
+ end if
98
+ ```
99
+
100
+ A useful IO feature are scratch files, which can be opened with `` status="scratch" `` .
101
+ They are automatically deleted after closing the unit identifier.
0 commit comments