File io 在Fortran中同时读取多个文件
我有500000个文件,我需要用Fortran阅读,每个文件有14000个条目(每个条目只有大约100个字符长)。我需要一次处理每个文件的每一行。例如,我需要处理所有500000个文件的第1行,然后再从文件中转到第2行,以此类推 我不能一次全部打开它们(我尝试创建一个文件指针数组并将它们全部打开),因为一次打开的文件太多了。相反,我想做以下几件事:File io 在Fortran中同时读取多个文件,file-io,fortran,File Io,Fortran,我有500000个文件,我需要用Fortran阅读,每个文件有14000个条目(每个条目只有大约100个字符长)。我需要一次处理每个文件的每一行。例如,我需要处理所有500000个文件的第1行,然后再从文件中转到第2行,以此类推 我不能一次全部打开它们(我尝试创建一个文件指针数组并将它们全部打开),因为一次打开的文件太多了。相反,我想做以下几件事: do iline = 1,Nlines do ifile = 1,Nfiles ! open the file ! re
do iline = 1,Nlines
do ifile = 1,Nfiles
! open the file
! read a line
! close the file
enddo
end
希望这能让我一次读一行(从每个文件中),然后转到下一行(在每个文件中)。不幸的是,每次我打开文件,它都会再次从第1行开始。有没有办法打开/关闭一个文件,然后在之前停止的位置再次打开它
谢谢不幸的是,在标准Fortran中,以这种方式是不可能的。即使你指定
position="ASIS"
对于尚未连接的单元,实际位置将未指定,并且在大多数系统上实际上是文件的开头
这意味着你必须使用
read(*,*)
有足够的时间在文件中找到正确的位置
您还可以使用stream
access。文件将在开始时再次打开,但您可以使用
read(u,*,pos=n) number
其中n
是上次打开时保存的位置。你可以从
inquire(unit=u, pos=n)
n = n
您可以使用acess=“STREAM”
打开文件
另外,打开50万个文件确实太多了。有一些方法可以查询系统限制以及如何控制它们,但是编译器也可能有一些限制
其他解决方案:您不能将文件的内容存储在内存中吗?今天,几GB是可以的,但对您来说可能还不够。您可以尝试使用和,如下所示
! initialize an array of 0's
do iline = 1,Nlines
do ifile = 1,Nfiles
! open the file
! fseek(fd, array(ifile))
! read a line
! array(ifile)=ftell(fd)
! close the file
enddo
end
(未测试的)想法是将每个文件的偏移量存储在一个数组中,并在打开文件时将光标定位在该位置。然后,读取一行后,
ftell
检索当前位置,并将其保存到内存中以供下一轮使用。如果所有条目的长度相同,则可以保留数组并只存储一个值。如果文件具有固定的记录长度,即恒定的记录长度,则可以使用直接访问。然后,您可以“直接”读取特定记录。然而,一个很大的“如果”。所有文件打开/关闭的开销将是一个很大的性能瓶颈。
在给定内存的情况下,应尽可能多地读取每个打开操作的内容:
伪代码:
loop until done:
loop over all files:
open
fseek !as in damiens answer
read N lines into array ! N=100 eg.
save ftell value for file
close
end file loop
loop over N output files:
open
write array data
close
所有数据的内容都超过130 GB。我无法将其存储到内存中,否则这将是一个简单的修复。我实际上是这样读的,因为所有的数据都在一个文件中,我必须以一种需要4.5年才能完成的方式来读!所以是的,我可以改变算法,目前的版本是目前为止最好的选择!您也可以尝试
流
访问,但速度可能不会更快。太棒了。在我尝试这个之前,我使用了一个穷人的FSEEK
,只是用reads搜索指定的行。对10个文件执行此操作需要约8分钟,但现在使用FSEEK
非标准Fortran将时间缩短到约4秒。我认为此标题有点误导,因为问题不是实际同时打开所有这些文件。对于管理如此大量的文件和数据,这似乎也是一种令人惊讶的非复杂化方法。你考虑过建立一个数据库管理系统吗?