File io 无需提前阅读自由格式
在给定的文件记录中,我首先需要读取前两个整数元素,然后读取行的其余部分(大量实数元素),因为赋值依赖于前两个。假设前两个整数元素的格式没有很好地定义 解决问题的最佳方法可能是:File io 无需提前阅读自由格式,file-io,io,fortran,File Io,Io,Fortran,在给定的文件记录中,我首先需要读取前两个整数元素,然后读取行的其余部分(大量实数元素),因为赋值依赖于前两个。假设前两个整数元素的格式没有很好地定义 解决问题的最佳方法可能是: read(unitfile, "(I0,I0)", advance='no') ii, jj read(unitfile,*) aa(ii,jj,:) 但在我看来,gfortran中不允许使用“(I0)”规范 基本上,在unitfile中读取的文件可能类似于: 0 0 <floats> 0 1
read(unitfile, "(I0,I0)", advance='no') ii, jj
read(unitfile,*) aa(ii,jj,:)
但在我看来,gfortran中不允许使用“(I0)”规范
基本上,在unitfile中读取的文件可能类似于:
0 0 <floats>
0 10 <floats>
10 0 <floats>
100 0 <floats>
100 100 <floats>
0
0 10
10 0
100 0
100 100
使用任何类似fortran的固定字段格式规范都很难读取
有没有其他方法可以解决这个看似微不足道的问题?这将应用字符串操作来获取各个组件,并用空格
'
和/或制表符(char(9)
)分隔:
对于.txt中的文件,例如:
1 2 3.0 4.0 5.0
这导致
./a.out
3.00000000 4.00000000 5.00000000
注意:这只是一个简单的例子,请根据您的需要进行调整 [这个答案已被大幅修改:原来的答案不安全。感谢IanH指出这一点。]
当我负担得起的时候,我通常会尽量避免使用非列表导向的格式化输入。对于字符串解析,已经有了一个非常通用的答案,但我将提供一些关于更简单设置的建议
当您对信任输入感到放松时,例如当格式有点棘手时(或者您很乐意将其留给编译器的边界检查),您可以使用
read(unitfile, *) ii, jj, aa(ii, jj, :)
或者,如果数组部分比前两列直接给出的更复杂,那么它可以是表达式,甚至是函数
read(unitfile, *) ii, jj, aa(fi(ii,jj), fj(ii,jj), :fn(ii,jj))
使用纯整数函数fi(ii,jj)
等,这些函数甚至有可能进行范围验证(例如,返回大小为0的部分)
在更一般的情况下,但保持列表定向,可以为实际变量使用缓冲区
read(unitfile, *) ii, jj, buffer(:) ! Or ... buffer(:fn(ii,jj))
! Validate ii and jj before attempting to access aa with them
aa(.., .., :) = buffer
缓冲区大小合适的地方
您首先考虑的方法表明您对行的结构(包括长度)有一些合理的想法,但是当ii
和jj
中的real数未知,或者类型(不允许多态读取)未知时,事情确实变得棘手。此外,如果一个人对验证输入非常敏感,甚至对错误提供有意义的详细用户反馈,这不是最佳选择
最后,iostat
有帮助。i0
不允许在gfortran中读取文件,但肯定可以用于写入文件。你试过类似i3的东西吗?好的:谢谢@Kyle。不,它不起作用i3:看最后一个例子:您将无法正确读取第二个元素。。。。然而,我希望找到最普遍的解决方案。那么你的选择是要么使用@AlexanderVogt的将行作为字符串读取&必要时重复,要么使用不同的编译器。我更改了代码并使用gcc
(fprintf(fp,%d%d%f%f%f\n),I,j,(double)(I+j),(double)(I-j),(double)(j-I));
)编写文件,并使用ifort
读取它,使用read(10'(i0,i0'),advance='no'时没有任何问题)
@KyleKanos I0在输入格式规范中不是标准的F2008。列表定向输入可能适合内部用途,您可以很好地控制输入的质量,但对于一般用户提供的输入,它在验证和其他“令人惊讶”的功能方面存在严重缺陷。谢谢。我已经用gfortran测试了最简单的读取(unitfile,*)ii、jj、aa(ii、jj,:)
,但我不确定它是否正常工作。@gluke您想读取的real数有多大?另外,aa
的尺寸是多少?还有,它是否可以在一个较小的情况下工作/失败,您可以将其粘贴到这里?@francescalus我终于按照您的建议使用一个类似缓冲区的数组解决了这个问题,使用自由格式,并在下一步进行赋值。问题还在于,我不知道需要读取多少条记录,也就是说,我还必须使用iostat
。
read(unitfile, *) ii, jj, buffer(:) ! Or ... buffer(:fn(ii,jj))
! Validate ii and jj before attempting to access aa with them
aa(.., .., :) = buffer