Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Beginner
27 Views

OPEN with position= keyword

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'

--------------------------

open(newUnit=lfnData,file=trim(filePathData),access='STREAM',position='REWIND',status=stText,action='READWRITE',share='DENYNONE',ioStat=iStat)

open(newUnit=lfnInsert,file=trim(filePathInsert),access='STREAM',position='REWIND',status='UNKNOWN',action='READWRITE',share='DENYNONE',ioStat=iStat)

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

write(10,*)istat

open(lfnInsert,position='APPEND',ioStat=iStat) !gFortran seems to work

write(10,*)istat

 

0 Kudos
4 Replies
Highlighted
Black Belt Retired Employee
27 Views

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:

  1. Open the file POSITION='APPEND'.
  2. Do an INQUIRE (ifnData,POS=lastpos) ! Declare lastpos as integer
  3. REWIND (ifnData)
  4. Do your writes
  5. Do a WRITE (ifnData,POS=lastpos) ! with no I/O list
  6. 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

And got:

D:\Projects>t.exe
          11
          12
           3
           4
           5
           6
           7
           8
           9
          10
          13
          14

 

--
Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
Beginner
27 Views

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.

0 Kudos
Highlighted
Black Belt Retired Employee
27 Views

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?

--
Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
Valued Contributor III
27 Views

.. 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

Upon execution,

 Compiler Version:
 Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(

 R) 64, Version 19.0.0.117 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!

 

0 Kudos