使用 fortran 覆盖文件
overwrite a file using fortran
我正在使用写入文件的 Fortran 90 程序。该文件的第一行应该指示剩余文件中的行数。该文件是在满足特定条件且无法事先确定时由程序写入的。基本上,等到运行结束了,我才会知道总行数。
我想按以下方式进行:
1) 打开文件并在第一行写上一些文字,比如“Hello”
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 支持三种文件访问形式 - DIRECT、STREAM (F2003+) 和 SEQUENTIAL。 DIRECT 和 STREAM 访问都支持重写文件的较早部分,而 SEQUENTIAL 访问则不支持(重写较早的记录会在重写的记录处截断文件)。
通过直接访问,文件中的所有记录长度相同。通过简单地在语句中指定相关记录号,任何 input/output 语句都可以 [必须] 访问任意记录。但请注意,直接访问文件的典型磁盘格式可能与您对 "lines".
文件的想法不符
通过格式化流访问,可以使用 INQUIRE 语句捕获文件中的当前位置,然后稍后的 input/output 语句可以使用 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
流访问:
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
我正在使用写入文件的 Fortran 90 程序。该文件的第一行应该指示剩余文件中的行数。该文件是在满足特定条件且无法事先确定时由程序写入的。基本上,等到运行结束了,我才会知道总行数。
我想按以下方式进行:
1) 打开文件并在第一行写上一些文字,比如“Hello”
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 支持三种文件访问形式 - DIRECT、STREAM (F2003+) 和 SEQUENTIAL。 DIRECT 和 STREAM 访问都支持重写文件的较早部分,而 SEQUENTIAL 访问则不支持(重写较早的记录会在重写的记录处截断文件)。
通过直接访问,文件中的所有记录长度相同。通过简单地在语句中指定相关记录号,任何 input/output 语句都可以 [必须] 访问任意记录。但请注意,直接访问文件的典型磁盘格式可能与您对 "lines".
文件的想法不符通过格式化流访问,可以使用 INQUIRE 语句捕获文件中的当前位置,然后稍后的 input/output 语句可以使用 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
流访问:
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