我有一个shell脚本,我将二进制文件传递给fortran程序,以便
Mth=$1
loop=1
it=1
while test $it -le 12
do
Mth=`expr $Mth + $loop`
file="DataFile"$Mth".bin"
./fort_exe ${Yr} ${nt} ${it}
# Increment loop
it=`expr $it + 1`
done
此脚本用于将do循环中的12个文件传递给fortran程序。在fortran程序中,我读取了从shell脚本传递的二进制文件,我正在尝试编写第二个文件,该文件将在单个文件中编译从连续文件中读取的所有数据,例如。
!Open binary file passed from shell script
open(1,file='Datafile'//TRIM{Mth)//.bin',action='read',form='unformatted',access='direct', &
recl=4*x*y, status='old')
! Open write file for t 1. The status is different in t 1 and t > 1 so I open it twice: I guess there is a more elegant way to do this...
open(2,file='Newfile.bin',action='write',form='unformatted', &
access='stream', position='append', status='replace')
irec = 0
do t = 1, nt
! Read input file
irec = irec + 1
read(1,rec=irec) val(:,:)
! write output file
irecW= irec + (imonth-1)*nt
if ( t .eq. 1) write(2,pos=irecW) val(:,:)
! Close file after t = 1, update the status to old and reopen.
if ( t .eq. 2) then
close (2)
open(2,file='Newfile.bin',action='write',form='unformatted', &
access='stream', position='append',status='old')
endif
if ( t .ge. 2) write(2,pos=irecW) val(:,:)
enddo
我可以从第一个文件读取二进制数据没问题,但是当我尝试从另一个程序读取我在第一个程序中写入的文件中的二进制数据时
open(1,file='Newfile.bin',action='read',form='unformatted', &
access='stream', status='old')
irec=0
do t = 1, nt
! Read input file
irec = irec + 1
read(1,pos=irec) val(:,:)
write(*,*) val(:,:)
enddo
val(:,:)只是一个零列表。这是我第一次使用access = stream,我认为这是我可以使用position ='append'的唯一方法。我尝试使用gfortran和ifort进行编译,但我没有收到任何错误消息。
有谁知道为什么会这样?
答案 0 :(得分:0)
首先,我不认为您需要关闭并重新打开输出文件。 status
说明符仅与其显示的open
语句相关:replace
如果当时存在,则会删除Newfile.bin
,然后再打开一个新文件名称。状态隐式更改为old
,但这不会影响对文件执行的任何操作。
但是,由于你的Fortran代码不知道你运行了12次,你应该有办法确保文件只在第一次被替换,之后被打开为old
;否则,Newfile.bin
将仅包含上一个处理文件的信息。
至于读错值,这很可能是因为直接访问(您可以选择记录长度)和流访问(您不能访问)之间的差异。通过流访问,数据被存储为一系列“文件存储单元”。它们的大小通常取决于编译器,但可以通过模块iso_fortran_env
作为file_storage_size
;它通常是8位。这意味着每个条目通常占用多个存储单元,因此您必须注意使用pos =
说明符的读取或写入不会访问错误的存储单元。
修改强>
一些示例代码使用流访问进行编写和读取:
program stream
use, intrinsic :: iso_fortran_env
implicit none
integer :: i, offset
real(real32), dimension(4,6) :: val, nval
open(unit=2, file='Newfile.bin', action='readwrite', form='unformatted', &
access='stream', status='replace')
do i = 1,2
call random_number(val)
write(2) val
enddo
! The file now contains two sequences of 24 reals, each element of which
! occupies the following number of storage units:
offset = storage_size(val) / file_storage_size
! Retrieve the second sequence and compare:
read(2, pos = 1 + offset*size(val)) nval
print*, all(nval == val)
close(2)
end program
值 true 应打印在屏幕上。
另请注意,在将数据写入文件时,并不一定要指定pos
,因为该文件将自动定位在读取或写入的最后一条记录之外。
也就是说,如果您需要以非顺序方式访问数据,则直接访问或流访问是最有益的。如果您只需要将输入文件合并为一个,则可以更容易地使用顺序访问来编写输出文件,您也可以为其指定recl
和position = 'append'
。
答案 1 :(得分:0)
您可以使用inquire
语句检查标准Fortran中是否存在文件:
logical :: exist
inquire(file="test.dat", exist=exist)
if (exist) then
print *, "File test.dat exists"
else
print *, "File test.dat does not exist"
end if
或者你可以查看提供libc文件操作例程的modFileSys库。
关于追加和流:当你使用“经典”基于记录的fortran文件时,也可以附加文件,你不必为此使用流。