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

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

问题描述

保存样本数据的变量 save 的二进制快照的最佳方法是什么在下面的类型?

 程序save_it 

核心
整数,维度(8): :indx
结束类型核心

类型示例
integer :: a
real * 8,dimension(:),allocatable :: b
类型核心),维(:),allocatable :: c
结束类型示例

!这里是
类型(示例):: save

!这里我们分配变量save
!的所有组件。
!。

!现在,如何写/读变量保存到/从外部文件?

结束程序save_it

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

解决方案

Fortran 2003,则可以选择用户定义的派生类型IO。这允许您在写入语句中包含分配所需的额外簿记。我将在底部放置示例代码。



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



关键部分是发送并回读尺寸并分配

代码:

 模块类型

类型核心
整数,维度(8):: indx
结束类型核心

类型示例
整数:: a
real * 8,dimension(:),allocatable :: b
类型(核心),dimension(:),allocatable :: c
包含
过程write_sample
过程read_sample
generic :: write(unformatted)=> write_sample
generic :: read(unformatted)=> read_sample
结束类型示例

包含

!未定义格式的示例派生类型
子例程write_sample(dtv,unit,iostat,iomsg)
class(s​​ample),intent(in):: dtv
整数,意图(in)::单位
整数,意图(出):: iostat
字符(*),意图(inout):: iomsg

整数

!写一个给出分配大小的记录
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))

结束子程序write_sample

!未定义样本的派生类型
子程序read_sample(dtv,unit,iostat,iomsg)
class(s​​ample),intent(inout):: dtv
整数,意图(in)::单位
整数,意图(出):: iostat
字符(*),意图(inout):: iomsg

整数
整数sizeb,sizec

!我们首先有一条记录告诉我们组件的大小
read(unit,iostat = iostat,iomsg = iomsg)sizeb,sizec
!所以我们做分配
分配(dtv%b(sizeb),dtv%c(sizec))
!最后是阅读。
read(unit,iostat = iostat,iomsg = iomsg)dtv%a,dtv%b,&
(dtv%c(i)%indx,i = 1,SIZE(dtv%c))

结束子程序read_sample

结束模块类型

程序save_it
使用类型

隐含无

整数i,unit_in,unit_out

!这里是
类型(样品):: save
类型(样品):: save_test

!定义一些值 - 使用ifort不要忘记设置编译标志
save%a = 14
save%b = [(i * 1。,i = 1,10)]
保存%c = [core([(i,i = 1,8)]),core([(i,i = 11,18)])]

!写出派生类型
open(newunit = unit_out,file ='serial',form ='unformatted',&
status ='replace',action ='write')
write (unit_out)保存
close(unit_out)

!在派生类型中读入一个新类型
open(newunit = unit_in,file ='serial',form ='unformatted',&
status ='old',action ='read')
read(unit_in)save_test
close(unit_in)

!测试,如果我们想确定

结束程序save_it

肯定有需要做很多工作才能使其健壮。


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 

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

解决方案

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.

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.

The code:

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天全站免登陆