Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

User-defined derived-type i/o

Simon_Geard
New Contributor I
1,134 Views

I'm trying to find a way of using this to serialize some data. The problem I'm having is that the data are already written into a direct-access file but I can't find a way to use the DTIO functionality to interact with this type of file - for the DTIO to work it seems the file has to be opened as sequential,unformatted. Is it possible to use direct access? Is closing the unit inside the read(unformatted) subroutine and reopening as direct,unformatted a safe thing to to?

Thanks,

Simon

0 Kudos
1 Solution
Steven_L_Intel1
Employee
1,134 Views

Here's my test program (which doesn't work - bug filed.)

module mymod
  
    type mytype
        integer a,b
    contains
    procedure :: pru
    procedure :: pwu
    generic :: READ(UNFORMATTED) => pru
    generic :: WRITE(UNFORMATTED) => pwu
    end type mytype
    
    contains
    subroutine pru (dtv,unit,iostat,iomsg)
    class(mytype), intent(INOUT) :: dtv
    integer, intent(IN) :: unit
    integer, intent(OUT) :: iostat
    character(*), intent(INOUT) :: iomsg
    
    read (unit,iostat=iostat, iomsg=iomsg) dtv%a,dtv%b
    end subroutine pru  
    
    subroutine pwu (dtv,unit,iostat,iomsg)
    class(mytype), intent(IN) :: dtv
    integer, intent(IN) :: unit
    integer, intent(OUT) :: iostat
    character(*), intent(INOUT) :: iomsg
    
    write (unit,iostat=iostat, iomsg=iomsg) dtv%a,dtv%b
    end subroutine pwu
    end module mymod

    program U537051
    use mymod
    implicit none
    type(mytype) :: t
    integer :: ios
    character(100) :: imsg

    open (unit=1,file='file.dat',form='unformatted',access='direct',recl=2)
    t%a = 3
    t%b = 4
    write (1,rec=4,iostat=ios,iomsg=imsg) t
    if (ios == 0) then
        write (*,*) "write succeeded"
    else
        write (*,*) "Write failed with ",trim(imsg)
    end if
    
    close (1)
    open (unit=1,file='file.dat',form='unformatted',access='direct',recl=2,status='old')
    t = mytype(0,0)
    read (1,rec=4,iostat=ios,iomsg=imsg) t
      if (ios == 0) then
        write (*,*) "read",t%a,t%b, "should be",3,4
    else
        write (*,*) "Read failed with ", trim(imsg)
    end if
  
    end program U537051

 

View solution in original post

0 Kudos
6 Replies
Steven_L_Intel1
Employee
1,134 Views

You are mistaken that UDIO is restricted to sequential I/O. However, inside the child routine you do a sequential read or write to the passed in unit. You are NOT allowed to close and reopen the unit inside the child routine.

However, I've done some testing and things aren't quite working right. Let me look into this some more.

0 Kudos
Steven_L_Intel1
Employee
1,134 Views

Something's definitely wrong - the child procedure isn't even being called in my test case. Escalated as issue DPD200364274.

0 Kudos
Simon_Geard
New Contributor I
1,134 Views

Thanks for this info. I wasn't expecting closing the unit insdie the child routine to be a good idea and have already deleted that bit of code!

All the examples I've seen for UDIO have been for sequential formatted/unformatted access, e.g. https://software.intel.com/en-us/node/511145

If it isn't restricted to sequential access could you give an example of using direct access please.

Thanks.

0 Kudos
Steven_L_Intel1
Employee
1,135 Views

Here's my test program (which doesn't work - bug filed.)

module mymod
  
    type mytype
        integer a,b
    contains
    procedure :: pru
    procedure :: pwu
    generic :: READ(UNFORMATTED) => pru
    generic :: WRITE(UNFORMATTED) => pwu
    end type mytype
    
    contains
    subroutine pru (dtv,unit,iostat,iomsg)
    class(mytype), intent(INOUT) :: dtv
    integer, intent(IN) :: unit
    integer, intent(OUT) :: iostat
    character(*), intent(INOUT) :: iomsg
    
    read (unit,iostat=iostat, iomsg=iomsg) dtv%a,dtv%b
    end subroutine pru  
    
    subroutine pwu (dtv,unit,iostat,iomsg)
    class(mytype), intent(IN) :: dtv
    integer, intent(IN) :: unit
    integer, intent(OUT) :: iostat
    character(*), intent(INOUT) :: iomsg
    
    write (unit,iostat=iostat, iomsg=iomsg) dtv%a,dtv%b
    end subroutine pwu
    end module mymod

    program U537051
    use mymod
    implicit none
    type(mytype) :: t
    integer :: ios
    character(100) :: imsg

    open (unit=1,file='file.dat',form='unformatted',access='direct',recl=2)
    t%a = 3
    t%b = 4
    write (1,rec=4,iostat=ios,iomsg=imsg) t
    if (ios == 0) then
        write (*,*) "write succeeded"
    else
        write (*,*) "Write failed with ",trim(imsg)
    end if
    
    close (1)
    open (unit=1,file='file.dat',form='unformatted',access='direct',recl=2,status='old')
    t = mytype(0,0)
    read (1,rec=4,iostat=ios,iomsg=imsg) t
      if (ios == 0) then
        write (*,*) "read",t%a,t%b, "should be",3,4
    else
        write (*,*) "Read failed with ", trim(imsg)
    end if
  
    end program U537051

 

0 Kudos
Simon_Geard
New Contributor I
1,134 Views

Thanks. I had the same problem with the procedure not being call and just assummed I had made a mistake. I'll look forward to the fix, hopefully in the v15 stream.

0 Kudos
Steven_L_Intel1
Employee
1,134 Views

It will be fixed in version 16.

0 Kudos
Reply