10. Printing and files
probe writes its vertices: on the screen, into a binary file and a text file, into a stream file from which it reads one vector straight away, and past its end, to see the error.
program probe
!< Tutorial, chapter 10: printing, saving and loading the vertices.
use, intrinsic :: iso_fortran_env, only : int64
use penf, only : R8P
use vecfor, only : ex, ey, ez, vector
implicit none
type(vector) :: o ! the origin
type(vector) :: p(4) ! the vertices
type(vector) :: r(4) ! the vertices read back
integer :: u ! a file
integer :: i ! counter
integer :: ios ! I/O status
character(len=200) :: msg ! I/O message
p(1) = o ; p(2) = ex ; p(3) = ey ; p(4) = ez
call p(2)%printf(prefix='p2 = ')
call p(2)%printf(prefix='p2 = [', sep='; ', suffix=']')
open(newunit=u, file='vertices.bin', form='unformatted', status='replace')
do i = 1, 4
call p(i)%save_into_file(unit=u) ! binary: the exact bits
enddo
rewind(u)
do i = 1, 4
call r(i)%load_from_file(unit=u)
enddo
close(u)
print '(A,L1)', 'read back equal: ', all(r == p)
open(newunit=u, file='vertices.txt', status='replace')
do i = 1, 4
call p(i)%save_into_file(unit=u, fmt='(3F6.2)')
enddo
close(u)
open(newunit=u, file='vertices.raw', access='stream', form='unformatted', status='replace')
do i = 1, 4
call p(i)%save_into_file(unit=u)
enddo
print '(A,I0)', 'bytes per vector: ', o%iolen()
call r(1)%load_from_file(unit=u, pos=2 * int(o%iolen(), int64) + 1) ! the third vector, straight away
call r(1)%printf(prefix='third vector = ')
call r(1)%load_from_file(unit=u, pos=4 * int(o%iolen(), int64) + 1, iostat=ios, iomsg=msg)
print '(A,I0,2A)', 'reading past the end: iostat = ', ios, ', ', trim(msg)
close(u)
endprogram probe$ probe && cat vertices.txt
p2 = +1.0, +0.0, +0.0
p2 = [+1.0; +0.0; +0.0]
read back equal: T
bytes per vector: 24
third vector = +0.0, +1.0, +0.0
reading past the end: iostat = -1, End of file
0.00 0.00 0.00
1.00 0.00 0.00
0.00 1.00 0.00
0.00 0.00 1.00Printing
call v%printf writes one line on standard output: the prefix (empty by default), the three components separated by sep (', ' by default), then the suffix (empty). Each number has the shortest digits that read back as the same value. unit= sends the line to another unit, an open file or standard error (see Printing a vector).
Saving and loading
call v%save_into_file(unit=u) writes the three components to the unit u, open by you; call v%load_from_file(unit=u) reads them back. Both write or read one record of three numbers, in the form of the unit:
- unformatted: the exact bits, 24 bytes per double precision vector; what is read back is equal to what was written,
r == p. - formatted, with
fmt=, a format for three reals such as'(3F6.2)': a text file, readable and portable, which keeps only the digits of the format.fmtis a format string;'*'(list-directed) is not supported.
Stream files and positions
On a unit opened with access='stream', pos= is the position, in file storage units (bytes, with gfortran), at which the vector is written or read. o%iolen() (or iolen(o)) is the number of storage units of one vector, the value of inquire(iolength=): 24 for double precision. The third vector starts at 2 * 24 + 1, and is read without reading the two before it. pos is an integer(I8P) (64 bits), hence the int(..., int64). For a direct access file, iolen is the record length, recl= (see A direct access file of vectors).
Errors
All three procedures take the optional iostat and iomsg of Fortran I/O, and with them the status and the message come back: reading past the end of the file gives iostat = -1, End of file; a malformed number in a text file gives a positive status (see An I/O error caught).
Always pass iostat
Unlike a plain read or write, these procedures never stop the program on an error: without iostat, a failed read or write is silently ignored, and the vector keeps the value it had. Pass iostat and check it.
What you learned
printf with prefix, sep, suffix and unit; save_into_file and load_from_file, unformatted, formatted with fmt, at a position with pos; iolen; iostat and iomsg. Reference: Input and output.
Next: 11. On the GPU.