Fortran写入二进制文件:Fortran运行时错误:直接访问数据传输需要记录号

时间:2016-06-14 14:09:39

标签: file binary fortran

我的代码

program v3

implicit none

real :: xmin,xmax,ymin,ymax,zmin,zmax,size
integer :: nx,ny,nz,i,j,nodestotal,sizeofinteger
real,dimension(:), allocatable :: v
integer,dimension(:), allocatable :: v1
integer,dimension(:,:), allocatable :: vel

sizeofinteger=2

open(unit=34, file='for.header', status='old')
read(34,115) xmin,xmax,ymin,ymax,zmin,zmax,size,nx,ny,nz
115   format(7f10.3,3i10)

nodestotal=nx*ny*nz
allocate (v(nodestotal))
allocate (v1(nodestotal))
allocate (vel(nx,nz))

open(unit=35, file='vel.txt', status='unknown')
read(35,*)v

v1=nint(v)

vel=reshape(v1,(/ nx, nz /) )
write(*,*)vel(:,25)

open(unit=36, file='vel.mod', form='unformatted', access='direct', recl=nx*nz*sizeofinteger)
do i=1,nx
write(36)vel(i,:)
end do 

end program

如何指定记录长度?我很长时间没有使用过FORTRAN二进制文件。 我真的要在二进制文件中写入601(nx)int 25(nz)次。我已经将sizeofinteger改为32.我想将二维数组写入二进制文件,应该很简单。 遵循弗拉基米尔F的建议我改变了流访问,但这就是我得到的 od -f vel.mod

1623500       8.688e-42               0               0               0
1623520               0               0               0               0
*
1625140       8.688e-42               0               0               0
1625160               0               0               0               0
*
1626600       8.688e-42               0               0               0
1626620               0               0               0               0
*
1630240       8.688e-42               0               0               0
1630260               0               0               0               0
*
1631700       8.688e-42               0               0               0
1631720               0               0               0               0
*
1633340       8.688e-42               0               0               0
1633360               0               0               0               0
*
1635000       8.688e-42               0               0               0
1635020               0               0               0               0
*
1636440       8.688e-42               0               0               0
1636460               0               0               0               0
*
1640100       8.688e-42               0               0               0
1640120               0               0               0               0
*
1641540       8.688e-42               0               0               0
1641560               0               0               0               0
*
1643200       8.688e-42               0               0               0
1643220               0               0               0               0
*
1644640       8.688e-42               0               0               0
1644660               0               0               0               0
*
1646300       8.688e-42               0               0               0
1646320               0               0               0               0
*
1647740       8.688e-42               0               0               0
1647760               0               0               0               0
*
1651400       8.688e-42               0               0               0
1651420               0               0               0               0
*
1653040

它应该是6200.为什么?

2 个答案:

答案 0 :(得分:4)

最近我在一个回答中说,人们不应该直接指定recl,但仍有很多人这样做...... https://stackoverflow.com/a/37784431/721644

在该链接中使用inquire(iolength=myrecl),您将更加便携。

无论如何,使用流访问您的代码会更简单(结果文件是相同的):

open(unit=36, file='vel.mod', form='unformatted', access='stream')
do i=1,nx
  write(36) vel(i,:)
end do 
close(36)

答案 1 :(得分:0)

您已在open语句中指定了记录长度(recl参数)。该错误实际上是在抱怨write语句。在write语句中,您需要指定要编写的记录,以便使用

do i=1,nx
  write(36,rec=i)vel(i,:)
end do 

除了

注意,当您使用unformatted时,recl参数指定每条记录的字节数。

可以使用

找到每个整数的字节数
sizeofinteger = storage_size(i)/8

,您的记录长度将为recl=sizeofinteger*nz

更新

正如@IanH在评论中指出的那样,recl参数并不总是字节数,它实际上是编译器相关的。正如@VladimirF在回答中所指出的那样,可以使用recl确定运行时的正确inquire长度来获取iolength