在Fortran90 +中使用可分配组件进行二进制读/写数据类型 [英] Binary Read/Write of Data Types with Allocatable Components in 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(sample),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(sample),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屋!