I was expecting the following to work but seems not to for my 2017.5.267 configuration. The open with the position='append' keyword only, issues error 104 (which isn't in my help file) indicating an invalid position= keyword. I was attempting to first open in the rewind position and overwrite a time stamp, then simply reposition to the end and begin appending records. Instead, I seem to have to close and reopen with position=append. Yes, I did do a topic search first but didn't find anything.
PS, the value of stText is 'UNKNOWN'
write(lfnData,ioStat=iStat)maxTS !If in server mode...
write(lfnInsert,ioStat=iStat)maxTS !If in server mode...
open(lfnData,position='APPEND',ioStat=iStat) !gFortran seems to work
open(lfnInsert,position='APPEND',ioStat=iStat) !gFortran seems to work
Your program violates the Fortran standard. gfortran may allow it as an extension. Here's what the standard (F2018 FDIS) says (emphasis mine)
If the file to be connected to the unit is the: same as the file to which the unit is connected, a new connection is not established and values for any changeable modes (12.5.2) specified come into effect for the established connection the current file position is unaffected. Before any effect on changeable modes, a wait operation is performed for any pending asynchronous data transfer operations for the specified unit. If the POSITION= specifier appears in such an OPEN statement, the value specified shall not disagree with the current position of the file. If the STATUS= specifier is included in such an OPEN statement, it shall be specified with the value OLD. Other than ERR=, IOSTAT=, and IOMSG=, and the changeable modes, the values of all other specifiers in such an OPEN statement shall not differ from those in effect for the established connection.
In your example, the current position is in the middle of the file, not at the end. What I think you can do is this:
- Open the file POSITION='APPEND'.
- Do an INQUIRE (ifnData,POS=lastpos) ! Declare lastpos as integer
- REWIND (ifnData)
- Do your writes
- Do a WRITE (ifnData,POS=lastpos) ! with no I/O list
- Append your records.
I tested this as follows:
open (1,file='stm.dat',form='unformatted',access='stream') do i=1,10 write (1) i end do inquire (1,POS=ipos) rewind (1) write (1) 11 write (1) 12 write (1,POS=ipos) write (1) 13 write (1) 14 rewind (1) do read (1,end=99) k print *, k end do 99 end
D:\Projects>t.exe 11 12 3 4 5 6 7 8 9 10 13 14
Hmm, that's quite unfortunate. There's no efficient mechanism to get to the end to begin appending records. My original design was to close the file and reopen at the append position. I was looking for a more efficient method than closing and reopening or reading to the end manually. I was also hoping to avoid the overhead on the write statement of processing the pos= keyword. I will explore the above inquire process further however. It doesn't seem much more efficient than just reading to the end. A better way would probably be a new statement that does the opposite of rewind (e.g. wind...probably internally implemented as a read loop, but can probably be done more efficiently). These are potentially 100s of MB files. Every nanosecond counts. It just strikes me as a minor hole in the available control statements for IO.
There's not really any overhead for the WRITE with POS= and no I/O list. It just does a "seek" to change the position - what you wanted to accomplish with the OPEN, and probably with far less overhead (I've seen what the code looks like to process an OPEN statement before it does anything at all, and it isn't short!)
So if the code you showed in the original post isn't really what you want to do, what is?
.. I was attempting to first open in the rewind position and overwrite a time stamp, then simply reposition to the end and begin appending records. ..
The advantage of "STREAM IO" is that one can easily perform data transfer in almost any order.
Given this facility, OP can do the file open with 'APPEND', write the extra data, then transfer the updated initial data (say time stamp) at initial position which is simply 1. See below where subprogram FPRINT mimics OP's stated desire. The code works fine with latest Intel Fortran:
program p use, intrinsic :: iso_fortran_env, only : compiler_version, iostat_end, iostat_eor implicit none character(len=*), parameter :: fname = "C:\temp\tmp.dat" character(len=*), parameter :: msg = " Hello World! " character(len=8) :: sdate character(len=10) :: stime print *, "Compiler Version: ", compiler_version() call date_and_time( sdate, stime ) call iprint() call rfile() call fprint() call rfile() stop contains subroutine iprint() integer :: lun open( newunit=lun, file=fname, access="stream", form="unformatted", status="replace" ) write( lun ) sdate, stime, msg close( lun ) return end subroutine subroutine fprint() integer :: lun integer :: istat character(len=2048) :: imsg character(len=8) :: ldate character(len=10) :: ltime character(len=*), parameter :: emsg = "I'm glad Fortran introduced stream access!" ! Open with position="append" open( newunit=lun, file=fname, access="stream", form="unformatted", status="old", & position="append", iostat=istat, iomsg=imsg ) if ( istat /= 0 ) then print *, "fprint: open failed - iostat=", istat print *, trim(imsg) stop end if write( lun ) emsg ! write extra data call date_and_time( ldate, ltime ) write( lun, pos=1 ) ldate, ltime ! update time stamp at beginning of file close( lun ) return end subroutine subroutine rfile() integer :: lun integer :: istat integer :: i integer, parameter :: iostat_zero = 0 character(len=2048) :: imsg open( newunit=lun, file=fname, access="stream", form="unformatted", status="old", & position="rewind", iostat=istat, iomsg=imsg ) if ( istat /= 0 ) then print *, "fprint: open failed - iostat=", istat print *, trim(imsg) stop end if i = 0 imsg = "" loop_read: do i = i + 1 if ( i > len(imsg) ) then print *, "File content exceeds buffer, read aborted." exit loop_read end if read( lun, pos=i, iostat=istat ) imsg(i:i) select case ( istat ) case ( iostat_zero ) ! continue reading case ( iostat_end, iostat_eor ) exit loop_read case default print *, "Error reading file at position ", i stop end select end do loop_read close( lun ) print *, "Contents of ", trim(fname), ":" print *, trim(imsg) return end subroutine end program p
Compiler Version: Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel( R) 64, Version 220.127.116.11 Build 20180804 Contents of C:\temp\tmp.dat: 20181027232615.376 Hello World! Contents of C:\temp\tmp.dat: 20181027232615.382 Hello World! I'm glad Fortran introduced stream access!