我有一个 Fortran 程序,正在将数组写入文件,但由于某种原因使用星号来表示多列:
8*9, 4, 2*9, 4
稍后从文件中读取时出现 I/O 错误:
lib-4190:不可恢复的库错误
数字输入字段包含无效字符。
在单元 10 的列表定向 READ 过程中遇到 Fortran 单元 10 连接到顺序格式化文本文件:
有谁知道为什么会发生这种情况,以及是否有一个标志可以提供给编译器来阻止它。我使用的是 Cray Fortran 编译器,写入语句如下所示:
write (lun,*) nsf_species(bundle%species(1:bundle%n_prim))
数据文件中的行读取如下所示:
read (lun,*) Info(ifile)%alpha_i(1:size)
我已检查以确保是这一行导致了问题。
在写出大量数据时,列表定向输出的压缩是 Cray 编译环境的一个非常有用的功能。然而,正如您所指出的那样,此压缩输出将无法正确读入(这不太有用)。
您可以修改此行为,不使用编译器标志,而是使用“分配”命令。
考虑这个示例代码:
PROGRAM test
IMPLICIT NONE
INTEGER :: u
OPEN(UNIT=u,FILE="f1",FORM="FORMATTED",STATUS="UNKNOWN")
WRITE(u,*) 0,0,0
CLOSE(u)
OPEN(UNIT=u,FILE="f2",FORM="FORMATTED",STATUS="UNKNOWN")
WRITE(u,*) 0,0,0
CLOSE(u)
END PROGRAM test
我们首先使用 CCE 构建并执行。文件 f1 和 f2 都包含压缩输出形式:
$ ftn -o test.x test.F90
$ ./test.x
$ cat f1
3*0
$ cat f2
3*0
现在我们将使用“分配”来修改文件f2中的格式。首先我们需要定义一个文件名来保存分配信息:
$ export FILENV=my_filenenv
现在我们使用 allocate 来关闭文件 f2 的压缩输出:
$ assign -y on f:f2
现在我们重新运行实验(无需重新编译):
$ ./test.x
$ cat f1
3*0
$ cat f2
0, 0, 0
有一些选项可以对所有文件、某些文件名模式或许多其他情况执行此操作。
分配还可以做其他事情。有关更多详细信息,请参阅加载了 PrgEnv-cray 的“man allocate”。
写入语句使用列表定向格式化(它仍然是格式化输出语句 - “格式化”意味着“格式化以便人类可以读取它”) - 如语句括号部分内的
*
所指定。 列表定向输出的规则为编译器提供了很大的自由度。 通常,如果您确实关心输出的细节,则应该提供明确的格式。
适用的规则之一是结果输出通常应适合列表定向输入。 但是对于允许作为列表定向格式化的输入的内容有一些相当令人惊讶的规则。 其中一项功能是,您可以使用语法
repeat*value
在输入文本中指定输入值的重复计数。
编译器注意到输出中存在重复值,因此它使用了此重复计数功能。
我不知道为什么在读取列表定向输入下的文件时会收到错误消息 - 因为您显示的行是列表定向输入的有效输入行。 确保导致错误的行实际上是您显示的行。
一个简单的解决方案是更改写入语句,使其不使用压缩格式。例如更改为:
write (lun,'(*(I5))') nsf_species(bundle%species(1:bundle%n_prim))
“*”允许指定格式任意次数的重复,并且应抑制压缩输出格式。
但是,如果编译器以压缩格式输出,那么它应该能够以相同的压缩格式读回。希望帮助台能够找到不起作用的根源。