2014-03-27 54 views
1

保存变量save的二进制快照的最佳方式是由sample以下的数据类型构成的?使用Fortran90中的可分配组件对二进制数据类型进行二进制读写+

program save_it 

    type core 
     integer, dimension(8) :: indx 
    end type core 

    type sample 
     integer :: a 
     real*8, dimension(:), allocatable :: b 
     type(core), dimension(:), allocatable :: c 
    end type sample 

    ! here it comes 
    type(sample) :: save 

    ! here we allocate all componenets of variable "save" 
    !. 
    !. 

    ! Now, how to write/read variable "save" to/from external file? 

end program save_it 

有非常直接的二进制输入/输出在C++流,但我不知道如何做到这一点用Fortran 90+。

回答

2

如果FORTRAN90 +你的意思是你是幸福的Fortran 2003的,再有就是用户自定义的派生类型IO的选项。这允许您在写入语句中包含分配所需的额外簿记。我会在底部放置示例代码。

如果你不想使用此功能,这是可能是因为你没有支持它(我用ifort 14测试)编译器,那么你可以仿效簿记很轻松了。

的关键部分是刚刚发出,并读回的大小和读取之前分配的变量。

代码:

module types 

    type core 
     integer, dimension(8) :: indx 
    end type core 

    type sample 
     integer :: a 
     real*8, dimension(:), allocatable :: b 
     type(core), dimension(:), allocatable :: c 
    contains 
     procedure write_sample 
     procedure read_sample 
     generic :: write(unformatted) => write_sample 
     generic :: read(unformatted) => read_sample 
    end type sample 

    contains 

    ! Unformatted writing for the sample derived type 
    subroutine write_sample(dtv, unit, iostat, iomsg) 
     class(sample), intent(in) :: dtv 
     integer, intent(in) :: unit 
     integer, intent(out) :: iostat 
     character(*), intent(inout) :: iomsg 

     integer i 

     ! Write a record giving sizes for the allocation 
     write(unit, iostat=iostat, iomsg=iomsg) SIZE(dtv%b), SIZE(dtv%c) 
     write(unit, iostat=iostat, iomsg=iomsg) dtv%a, dtv%b, & 
               (dtv%c(i)%indx, i=1,SIZE(dtv%c)) 

    end subroutine write_sample 

    ! Unformatted reading for the sample derived type 
    subroutine read_sample(dtv, unit, iostat, iomsg) 
     class(sample), intent(inout) :: dtv 
     integer, intent(in) :: unit 
     integer, intent(out) :: iostat 
     character(*), intent(inout) :: iomsg 

     integer i 
     integer sizeb, sizec 

     ! We first have a record telling us the sizes of components 
     read(unit, iostat=iostat, iomsg=iomsg) sizeb, sizec 
     ! So we do the allocation 
     allocate(dtv%b(sizeb), dtv%c(sizec)) 
     ! And then finally the reading. 
     read(unit, iostat=iostat, iomsg=iomsg) dtv%a, dtv%b, & 
              (dtv%c(i)%indx, i=1,SIZE(dtv%c)) 

    end subroutine read_sample 

end module types 

program save_it 
    use types 

    implicit none 

    integer i, unit_in, unit_out 

    ! here it comes 
    type(sample) :: save 
    type(sample) :: save_test 

    ! Define some values - using ifort don't forget to set the compile flag 
    save%a = 14 
    save%b = [(i*1., i=1, 10)] 
    save%c = [core([(i, i=1,8)]), core([(i, i=11, 18)])] 

    ! Write out the derived type 
    open(newunit=unit_out, file='serial', form='unformatted', & 
     status='replace', action='write') 
    write(unit_out) save 
    close(unit_out) 

    ! Read in the derived type to a new one 
    open(newunit=unit_in, file='serial', form='unformatted', & 
     status='old', action='read') 
    read(unit_in) save_test 
    close(unit_in) 

    ! Test, if we want to be certain 

end program save_it 

肯定还有很多工作要在让它更加强大完成。

+0

非常有洞察力的代码和伟大的想法!谢谢 – argasm

+0

请注意,子输入/输出语句总是被视为非前进 - write_sample和read_sample过程都只是在由主程序中的父写和读语句创建的单个记录中写入和读取它们的数据。 – IanH

+0

@IanH这很好,谢谢。也许在我的程序评论中,我应该说“块”而不是“记录”?或者有更少的负载/更正确的术语? – francescalus