Fortran90+ 中具有可分配组件的数据类型的二进制读/写 [英] Binary Read/Write of Data Types with Allocatable Components in Fortran90+

查看:13
本文介绍了Fortran90+ 中具有可分配组件的数据类型的二进制读/写的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

保存由以下 sample 数据类型组成的变量 save 的二进制快照的最佳方法是什么?

What is the best way to save a binary snapshot of the variable save which is made out of sample data type below?

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+ 中做到这一点.

There is pretty straight binary input/output streaming in C++ but I don't know how to do it in Fortran 90+.

推荐答案

如果说 Fortran90+ 意味着你对 Fortran 2003 很满意,那么可以选择用户定义的派生类型 IO.这允许您将分配所需的额外簿记包装在 write 语句中.我会把示例代码放在底部.

If by Fortran90+ you mean you are happy with Fortran 2003, then there is the option of user-defined derived type IO. This allows you to wrap the extra bookkeeping required for the allocation in the write statement. I'll put example code at the bottom.

如果您不想使用此功能,可能是因为您没有支持它的编译器(我已经使用 ifort 14 进行了测试),那么您可以很容易地模仿簿记.

If you don't want to use this feature, which is possibly because you don't have a compiler which supports it (I've tested with ifort 14), then you can mimic the bookkeeping easily enough.

关键部分只是发送和读取大小并在读取之前分配变量.

The crucial part is just sending out and reading back in the sizes and allocating the variables before the read.

代码:

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

要让它变得健壮,肯定还有很多工作要做.

There's certainly a lot of work to be done on making it robust.

这篇关于Fortran90+ 中具有可分配组件的数据类型的二进制读/写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆