我有需要在Fortran中读取的500,000个文件,每个文件中有大约14,000个条目(每个条目只有大约100个字符长)。我需要一次处理每个文件的每一行。例如,我需要为所有500,000个文件处理第1行,然后再从文件转到第2行,等等。
我无法一次打开它们(我尝试制作一个文件指针数组并打开它们),因为一次打开的文件太多了。相反,我想做一些如下事情:
do iline = 1,Nlines
do ifile = 1,Nfiles
! open the file
! read a line
! close the file
enddo
end
希望这允许我一次读取一行(从每个文件),然后转到下一行(在每个文件中)。不幸的是,每次打开文件时,它都会再次从第1行开始。有没有办法打开/关闭文件,然后再从上次停止的地方再次打开文件?
由于
答案 0 :(得分:3)
不幸的是,在标准的Fortran中不可能以这种方式。即使你指定
position="ASIS"
对于尚未连接的单元,未指定实际位置,实际上该位置实际上是大多数系统上文件的开头。
这意味着您必须使用
read(*,*)
足够的时间来到文件中的正确位置。
您还可以使用stream
访问权限。该文件将在开头再次打开,但您可以使用
read(u,*,pos=n) number
其中n
是从先前打开保存的位置。你可以从
inquire(unit=u, pos=n)
n = n
您可以使用acess="STREAM"
打开文件。
另外500000个打开的文件确实太多了。有多种方法可以查询系统限制以及如何控制它们,但是编译器可能还有一些限制http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/
其他解决方案:您无法将文件内容存储在内存中吗?今天几千兆字节还可以,但对你来说可能还不够。
答案 1 :(得分:0)
! 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
将检索当前位置,该位置将保存到下一轮的内存中。如果所有条目具有相同的长度,则可以节省数组并只存储一个值。
答案 2 :(得分:0)
如果文件具有固定的,即恒定的记录长度,则可以使用直接访问。然后你可以“直接”读取特定的记录。然而,这是一个很大的“如果”。
答案 3 :(得分:0)
所有文件打开/关闭的开销将是一个很大的性能瓶颈。 考虑到你的记忆,你应该尽可能多地阅读每次开放操作:
伪代码:
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