使用fortran覆盖文件
我正在使用Fortran 90程序编写一个文件。该文件的第一行应该指示剩余文件中的行数。当满足某个标准且无法事先确定时,该文件由程序写入。基本上,只有在运行结束后,我才能知道线路的总数 我想用以下方式来做: 1) 打开文件,写下第一行文字,说“你好” 2) 根据需要在文件中写入行,并为行数保留一个计数器 3) 运行结束后,在关闭文件之前,用计数器替换第一行字符串(“Hello”) 问题在第3步。我不知道如何更换第一行 我能想到的另一个选择是写入2个文件。首先,如上所述编写一个不带计数器的文件。运行结束后,关闭文件并写入另一个文件,这一次,我知道计数器的值使用fortran覆盖文件,fortran,fortran90,overwrite,Fortran,Fortran90,Overwrite,我正在使用Fortran 90程序编写一个文件。该文件的第一行应该指示剩余文件中的行数。当满足某个标准且无法事先确定时,该文件由程序写入。基本上,只有在运行结束后,我才能知道线路的总数 我想用以下方式来做: 1) 打开文件,写下第一行文字,说“你好” 2) 根据需要在文件中写入行,并为行数保留一个计数器 3) 运行结束后,在关闭文件之前,用计数器替换第一行字符串(“Hello”) 问题在第3步。我不知道如何更换第一行 我能想到的另一个选择是写入2个文件。首先,如上所述编写一个不带计数器的文件。运
我相信有一种方法可以继续第一种方法。有人能帮我一下吗?返回顺序访问文件很棘手,因为行的长度可能不同。如果你改变一行的长度,你必须把所有的东西移到后面 我建议在计算行数的同时将输出写入临时文件。然后,完成后,倒带临时文件,将行数写入输出文件,并将临时文件的内容复制到该输出文件 以下是我所做的:
program var_file
implicit none
character(len=*), parameter :: filename = 'delme.dat'
integer :: n, io_stat
character(len=300) :: line
open(unit=200, status='SCRATCH', action="READWRITE")
n = 0
do
read(*, '(A)') line
if (len_trim(line) == 0) exit ! Empty line -> finished
n = n + 1
write(200, '(A)') trim(line)
end do
rewind(200)
open(unit=100, file=filename, status="unknown", action="write")
write(100, '(I0)') n
do
read(200, '(A)', iostat=io_stat) line
if (io_stat /= 0) exit
write(100, '(A)') trim(line)
end do
close(200)
close(100)
end program var_file
Fortran支持三种形式的文件访问—直接、流(F2003+)和顺序。直接访问和流访问都支持重写文件的早期部分,而顺序访问则不支持(对早期记录的重写会在重写的记录处截断文件) 通过直接访问,文件中的所有记录长度相同。任何输入/输出语句都可以[必须]访问任意记录,只需在语句中指定相关记录编号即可。但是请注意,直接访问文件的典型磁盘格式可能与您对带有“行”的文件的想法不符 通过格式化流访问,可以使用INQUIRE语句捕获文件中的当前位置,然后稍后的输入/输出语句可以使用POS说明符在该位置开始数据传输。格式化流访问文件的典型磁盘格式通常与人们对带行文本文件的期望相匹配 流访问可能是您想要的。两种方法的示例如下所示 直接访问:
PROGRAM direct
IMPLICIT NONE
INTEGER :: unit
REAL :: r
INTEGER :: line
OPEN( NEWUNIT=unit, &
FILE='direct.txt', &
STATUS='REPLACE', &
ACCESS='DIRECT', &
RECL=15, & ! The fixed record length.
FORM='FORMATTED' )
CALL RANDOM_SEED()
! No need to write records in order - we just leave off
! writing the first record until the end.
line = 0
DO
CALL RANDOM_NUMBER(r)
IF (r < 0.05) EXIT
line = line + 1
PRINT "('Writing line ',I0)", line
! All the "data" records are offset by one, to allow the
! first record to record the line count.
WRITE (unit, "('line ',I10)", REC=line+1) line
END DO
! Now update the first record with the number of following "lines".
WRITE (unit, "(I10)", REC=1) line
CLOSE(unit)
END PROGRAM direct
直接编程
隐式无
整数:单位
REAL::r
整数::行
打开(新单元=单元&
FILE='direct.txt'&
状态为“替换”&
ACCESS='DIRECT'&
RECL=15,&!固定记录长度。
FORM='FORMATTED')
调用随机_SEED()
! 不需要按顺序写记录-我们只需停止
! 写入第一条记录直到结束。
直线=0
做
呼叫随机号码(r)
如果(r<0.05)退出
直线=直线+1
打印“('Writing line',I0)”,第行
! 所有“数据”记录都偏移一个,以允许
! 第一条记录以记录行计数。
写入(单位,“('line',I10)”,REC=line+1)行
结束
! 现在用下面的“行”数更新第一条记录。
写入(单位为“(I10)”,REC=1)行
关闭(单位)
结束程序直接
流访问:
PROGRAM stream
IMPLICIT NONE
INTEGER :: unit
REAL :: r
INTEGER :: line
INTEGER :: pos
OPEN( NEWUNIT=unit, &
FILE='stream.txt', &
STATUS='REPLACE', &
ACCESS='STREAM', &
POSITION='REWIND', &
FORM='FORMATTED' )
CALL RANDOM_SEED()
! Remember where we are. In this case, the position
! is the first file storage unit in the file, but
! it doesn't have to be.
INQUIRE(unit, POS=pos)
! Leave some space in the file for later overwriting
! with the number of lines. We'll stick the number
! zero in there for now.
WRITE (unit, "(I10)") 0
! Write out the varying number of lines.
line = 0
DO
CALL RANDOM_NUMBER(r)
IF (r < 0.05) EXIT
line = line + 1
PRINT "('Writing line ',I0)", line
WRITE (unit, "('line ',I10)") line
END DO
! Now update the space at the start with the number of following "lines".
WRITE (unit, "(I10)", POS=pos) line
CLOSE(unit)
END PROGRAM stream
程序流
隐式无
整数:单位
REAL::r
整数::行
整数::pos
打开(新单元=单元&
FILE='stream.txt'&
状态为“替换”&
访问流'&
位置='倒带'&
FORM='FORMATTED')
调用随机_SEED()
! 记住我们在哪里。在这种情况下,位置
! 是文件中的第一个文件存储单元,但
! 不一定是这样。
查询(单位,POS=POS)
! 在文件中留出一些空间,以便以后覆盖
! 有多少行。我们会记下号码的
! 现在是零。
写入(单位为“(I10)”)0
! 写出不同的行数。
直线=0
做
呼叫随机号码(r)
如果(r<0.05)退出
直线=直线+1
打印“('Writing line',I0)”,第行
写(单位,“('line',I10)”)行
结束
! 现在用下面的“行”数更新开头的空格。
写入(单位,“(I10)”,位置=位置)行
关闭(单位)
结束程序流
感谢您的详细回复和计划。这是我的后备计划。你帮我节省了写代码重写文件的时间。:)我会这样做的。我不能保证没有更好的,我不知道。谢谢你的信息。选择“流”是我应该走的路。显然,我的编译器不支持Access=stream。我错过了Fortran 90标记。Stream是Fortran 2003的一项功能。许多现代Fortran编译器现在都支持2003,包括Stream
——因此这是一个很有价值的答案,即使它在这种特殊情况下不起作用。不过,请允许我在回答中更清楚地指出,这只适用于符合2003标准的编译器。