【问题标题】:End of record error in file opening文件打开时记录结束错误
【发布时间】:2015-12-17 12:56:09
【问题描述】:

我目前正在编写代码来模拟粒子碰撞。我试图打开与粒子(N)一样多的文件,然后将位置和速度的数据放入每个文件中以进行时间积分的每个步骤(使用欧拉方法,但这不相关)。为此,我尝试使用 do 循环,这样它会打开我需要的所有文件——然后我稍后用不同的 do 循环将所有数据放入其中——然后将它们全部关闭。

我首先尝试做一个 do 循环来打开文件 - 但它给出了“文件已在另一个单元中打开”类型的错误,所以我做了以下操作:

module parameters
implicit none
character :: posvel
integer :: i, j, N
real :: tmax
real, parameter :: tmin=0.0, pi=3.14159265, k=500.0*10E3, dt=10.0E-5, dx=10.0E-3, g=9.806, ro=1.5*10E3
real, dimension(:), allocatable :: xold, xnew, vold, vnew, m, F, r
end module parameters

PROGRAM Collision
use parameters
implicit none

write(*,*) 'Enter total number of particles (integer number):'
read(*,*) N

allocate(xold(N))
allocate(vold(N))
allocate(xnew(N))
allocate(vnew(N))
allocate(m(N))
allocate(F(N))
allocate(r(N))

xold(1) = 0.0
vold(1) = 0.0
m(1) = 6.283*10E-9
r(1) = 10E-4

xold(2) = 5.0
vold(2) = 0.0
m(2) = 6.283*10E-9
r(2) = 10E-4

write(*,*) 'Type total time elapsed for the simulation(real number):'
read(*,*) tmax

do i = 1, N
    write(posvel,"(a,i3.3,a)") "posveldata",i,".txt"
    open(unit=i,file=posvel, status="unknown")
end do

do i = 1, N
    close(unit=i)
end do

END PROGRAM Collision

最后十行与我的问题有关。

这在代码块中有效——它只打开了我需要的文件数量,但我实际上使用的是 gfortran,它在写语句中给了我和“记录结束”错误。

我怎样才能让它正确执行并给我我需要的 N 个不同的文件?

P.S.:不是编译的问题,而是我执行程序后的问题。

【问题讨论】:

  • 请注意,在 gfortran 中,单元 1、5 和 6 对应于 stderr、stdin、stdout;你可能不想破坏那些。一般来说,在你自己的代码中只使用大于 10 的单元号,你应该是安全的(或者在 open 语句中使用 newunit= 说明符)。
  • 另请注意,如果您有很多粒子,为每个粒子创建一个文件会变得笨拙且缓慢。最好将所有内容放入一个文件中,例如en.wikipedia.org/wiki/XYZ_file_format 之类的东西编写和解析都非常简单。
  • 编译器和操作系统都可以对打开文件的数量进行限制。你肯定不想拥有成千上万个。在真正的分子动力学模拟中,您有数百万个粒子。为每个文件打开一个文件是个坏主意。此外,文件系统也会不愉快。打开一个包含太多文件的目录可能需要几分钟。
  • 我刚开始这个项目。我目前正在使用 2 - 5 个粒子来检查数学。我知道,伙计们,谢谢:)

标签: fortran fortran90


【解决方案1】:

参数模块中的字符串只有1个字符长度,所以不能包含完整的文件名。所以请使用更长的字符串,例如

character(100) :: posvel

然后您可以将每个文件打开为

do i = 1, N
    write(posvel,"(a,i0,a)") "posveldata",i,".txt"
    open(unit=i,file=trim(posvel), status="unknown")
end do

在这里,我使用格式 i0 自动确定整数的适当宽度,并使用 trim() 删除文件名中不必要的空格(尽管它们可能不是必需的)。 write 语句也可以更简洁地写成

write(posvel,"('posveldata',i0,'.txt')") i

通过将字符文字嵌入到格式规范中。


错误消息“记录结束”来自上述问题。这可以通过以下代码确认

character c

write(c,"(a)") "1"
print *, "c = ", c
write(c,"(a)") "23"   !! line 8 in test.f90
print *, "c = ", c

gfortran 给出的结果

c = 1
At line 8 of file test.f90
Fortran runtime error: End of record

这意味着虽然c 被用作内部文件,但这个“文件”没有足够的空间来容纳两个字符(这里是“23”)。为了比较,ifort14 给出了

c = 1
forrtl: severe (66): output statement overflows record, unit -5, file Internal Formatted Write

而 Oracle Fortran12 提供

c = 1
******  FORTRAN RUN-TIME SYSTEM  ******
Error 1010:  record too long
Location:  the WRITE statement at line 8 of "test.f90"
Aborted

(有趣的是,Oracle Fortran 报告记录“太长”,可能是指输入字符串。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多