第 2 章 Fortran 输入/输出 (Sun Studio 12:Fortran 编程指南)

您所在的位置:网站首页 mcafee自动删除Fortran生成的文件 第 2 章 Fortran 输入/输出 (Sun Studio 12:Fortran 编程指南)

第 2 章 Fortran 输入/输出 (Sun Studio 12:Fortran 编程指南)

2024-07-08 22:54| 来源: 网络整理| 查看: 265

第 2 章 Fortran 输入/输出

本章介绍 Sun Studio Fortran 95 编译器提供的输入/输出功能。

2.1 从 Fortran 程序内部访问文件

数据通过 Fortran 逻辑单元在程序、设备或文件间进行传送。逻辑单元在 I/O 语句中用逻辑单元号来标识,逻辑单元号是从 0 到最大 4 字节整数值 (2,147,483,647) 的非负整数。

字符 * 可以作为逻辑单元标识符出现。当星号出现在 READ 语句中时,它代表标准输入文件;当它出现在 WRITEPRINT 语句中时,则代表标准输出文件

Fortran 逻辑单元可通过 OPEN 语句与特定的命名文件相关联。另外,在程序开始执行时,某些预连接单元会自动与特定文件相关联。

2.1.1 访问命名文件

OPEN 语句的 FILE= 说明符在运行时建立逻辑单元到命名物理文件的关联。该文件可以是预先就有的,也可以由程序创建。

OPEN 语句中的 FILE= 说明符可以指定一个简单文件名 (FILE=’myfile.out’),也可以指定一个前面带有绝对或相对目录路径的文件名 (FILE=’../Amber/Qproj/myfile.out’)。另外,说明符还可以是字符常量、变量或字符表达式。

可以使用库例程将命令行参数和环境变量以字符变量形式送入程序,用作 OPEN 语句中的文件名。

以下示例 (GetFilNam.f) 展示了一种由键入的名称来构建绝对路径文件名的方法。程序使用库例程 GETENVLNBLNKGETCWD 返回 $HOME 环境变量的值,查找字符串中最后的非空格字符,确定当前工作目录:

CHARACTER F*128, FN*128, FULLNAME*128 PRINT*, ’ENTER FILE NAME:’ READ *, F FN = FULLNAME( F ) PRINT *, ’PATH IS: ’,FN END CHARACTER*128 FUNCTION FULLNAME( NAME ) CHARACTER NAME*(*), PREFIX*128 C This assumes C shell. C Leave absolute path names unchanged. C If name starts with ’~/’, replace tilde with home C directory; otherwise prefix relative path name with C path to current directory. IF ( NAME(1:1) .EQ. ’/’ ) THEN FULLNAME = NAME ELSE IF ( NAME(1:2) .EQ. ’~/’ ) THEN CALL GETENV( ’HOME’, PREFIX ) FULLNAME = PREFIX(:LNBLNK(PREFIX)) // 1 NAME(2:LNBLNK(NAME)) ELSE CALL GETCWD( PREFIX ) FULLNAME = PREFIX(:LNBLNK(PREFIX)) // 1 ’/’ // NAME(:LNBLNK(NAME)) ENDIF RETURN END

编译并运行 GetFilNam.f,结果如下:

demo% pwd /home/users/auser/subdir demo% f95 -o getfil GetFilNam.f demo% getfil ENTER FILE NAME: getfil PATH IS: /home/users/auser/subdir/atest.f demo%

2.1.4 向程序传递文件名中对这些例程进行了详细的介绍。有关详细信息,请参见 getarg(3F)、getcwd(3F) 和 getenv(3F) 的相应手册页条目;这些内容以及其他有用的库例程在《Fortran 库参考》中也有介绍。

2.1.2 不用文件名打开文件

OPEN 语句不需要指定名称;运行时系统会根据几个惯例提供文件名。

2.1.2.1 打开作为临时文件

OPEN 语句中指定 STATUS=’SCRATCH’ 会打开一个名称形式为 tmp.FAAAxnnnnn 的文件,其中 nnnnn 用当前进程 ID 替换,AAA 是一个包含三个字符的字符串,x 是一个字母;AAA 和 x 可确保文件名唯一。该文件在程序终止或执行 CLOSE 语句时被删除。在 FORTRAN 77 兼容模式 (-f77) 下编译时,可以在 CLOSE 语句中指定 STATUS=’KEEP’ 来保留这个临时文件。(此为非标准扩展。)

2.1.2.2 已打开

如果文件已被程序打开,可以使用后续的 OPEN 语句更改文件的某些特性;例如 BLANKFORM。此时,只需指定文件的逻辑单元号以及要更改的参数。

2.1.2.3 预连接或隐式命名单元

程序执行开始时,会自动将三个单元号与特定的标准 I/O 文件相关联。这些预连接单元是标准输入标准输出标准错误

标准输入是逻辑单元 5

标准输出是逻辑单元 6

标准错误是逻辑单元 0

通常,标准输入是从工作站键盘接收输入;标准输出和标准错误是在工作站屏幕上显示输出。

在其他所有情况下,如果在 OPEN 语句中指定了逻辑单元号而未在 FILE= 后指定任何名称,文件将以 fort.n 形式的名称打开,其中 n 为逻辑单元号。

2.1.3 不使用 OPEN 语句打开文件

在假定使用缺省惯例的情况下,并非必须使用 OPEN 语句。如果逻辑单元上的第一个操作是 I/O 语句,而不是 OPENINQUIRE,则会引用文件 fort.n,其中 n 为逻辑单元号(0、5 和 6 除外,它们有特殊意义)。

这些文件无需在程序执行前就存在。如果对文件的第一个操作不是 OPENINQUIRE 语句,则会创建这些文件。

示例:以下代码中,如果 WRITE 是该单元上的第一个输入/输出操作,则会创建文件 fort.25

demo% cat TestUnit.f IU=25 WRITE( IU, ’(I4)’ ) IU END demo%

上述程序将打开文件 fort.25,并将一条格式化记录写入该文件:

demo% f95 -o testunit TestUnit.f demo% testunit demo% cat fort.25 25 demo% 2.1.4 向程序传递文件名

文件系统没有任何自动工具可将 Fortran 程序中的逻辑单元号与物理文件相关联。

但是,有几种令人满意的方式可将文件名传递给 Fortran 程序。

2.1.4.1 通过运行时参数和 GETARG

可以使用库例程 getarg(3F) 在运行时将命令行参数读入字符变量。参数会被解释为文件名并在 OPEN 语句的 FILE= 说明符中使用:

demo% cat testarg.f CHARACTER outfile*40 C Get first arg as output file name for unit 51 CALL getarg(1,outfile) OPEN(51,FILE=outfile) WRITE(51,*) ’Writing to file: ’, outfile END demo% f95 -o tstarg testarg.f demo% tstarg AnyFileName demo% cat AnyFileName Writing to file: AnyFileName demo% 2.1.4.2 通过环境变量和 GETENV

同样,可以使用库例程 getenv(3F) 在运行时将任何环境变量的值读入字符变量,该字符变量随后被解释为文件名:

demo% cat testenv.f CHARACTER outfile*40 C Get $OUTFILE as output file name for unit 51 CALL getenv(’OUTFILE’,outfile) OPEN(51,FILE=outfile) WRITE(51,*) ’Writing to file: ’, outfile END demo% f95 -o tstenv testenv.f demo% setenv OUTFILE EnvFileName demo% tstenv demo% cat EnvFileName Writing to file: EnvFileName demo%

使用 getarggetenv 时,应该注意前导或尾随的空格。(Fortran 95 程序可以使用内函数 TRIM 或更早的 FORTRAN 77 库例程 LNBLNK())在本章开头的示例中,可以随 FULLNAME 函数的代码行编写更加灵活的代码来接受相对路径名。

2.1.4.3 命令行 I/O 重定向和管道

将物理文件与程序的逻辑单元号相关联的另一种方式是重定向或管道输送预连接的标准 I/O 文件。重定向或管道在运行时执行命令中使用。

采用这种方式,读取标准输入(单元 5)和写入标准输出(单元 6)或标准错误(单元 0)的程序可以通过重定向(在命令行中使用 、>>、>&、|、|&、2>、2>&1),读取或写入其他任何命名文件。

参见下表:

表 2–1 csh/sh/ksh 命令行重定向和管道

操作 

使用 C Shell 

使用 Bourne 或 Korn Shell 

标准输入-从 mydata 读取 

myprog < mydata

myprog < mydata

标准输出-写入(覆写)myoutput 

myprog > myoutput

myprog > myoutput

标准输出-写入/追加至 myoutput 

myprog >> myoutput

myprog >> myoutput

将标准错误重定向至文件 

myprog >& errorfile

myprog 2> errorfile

将标准输出通过管道输送至另一程序的输入 

myprog1 | myprog2

myprog1 | myprog2

将标准错误和输出通过管道输送至另一程序 

myprog1 |& myprog2

myprog1 2>&1 | myprog2

有关命令行重定向和管道的详细信息,请参见 cshkshsh 手册页。

2.2 直接 I/O

直接或随机 I/O 允许通过记录号直接访问文件。记录号在写入记录时分配。与顺序 I/O 不同,直接 I/O 记录可以按任何顺序读写。但是,在直接访问文件中,所有记录必须具有相同的固定长度。直接访问文件用文件的 OPEN 语句中的 ACCESS=’DIRECT’ 说明符声明。

直接访问文件中的逻辑记录是字节字符串,串长度由 OPEN 语句的 RECL= 说明符指定。READWRITE 语句指定的逻辑记录不能大于定义的记录大小。(记录大小以字节单位指定。)允许更短的记录。直接写入非格式化数据将使记录的未填写部分仍保持未定义。直接写入格式化数据将使未填写的记录用空格进行填充。

直接访问 READWRITE 语句另外还有一个参数 REC=n,用来指定要读取或写入的记录号。

示例:直接访问,非格式化:

OPEN( 2, FILE=’data.db’, ACCESS=’DIRECT’, RECL=200, & FORM=’UNFORMATTED’, ERR=90 ) READ( 2, REC=13, ERR=30 ) X, Y

本程序以直接访问、非格式化 I/O、记录固定长度为 200 字节的方式打开一个文件,然后将第十三条记录读入 X 和 Y。

示例:直接访问,格式化:

OPEN( 2, FILE=’inven.db’, ACCESS=’DIRECT’, RECL=200, & FORM=’FORMATTED’, ERR=90 ) READ( 2, FMT=’(I10,F10.3)’, REC=13, ERR=30 ) X, Y

本程序以直接访问、格式化 I/O、记录固定长度为 200 字节的方式打开一个文件。然后读取第十三条记录,并以 (I10,F10.3) 格式对其进行转换。

对于格式化文件,所写记录的大小由 FORMAT 语句确定。在上述示例中,FORMAT 语句所定义的记录大小为 20 个字符或字节。如果列表中的数据总量大于 FORMAT 语句中指定的记录大小,则可通过单条格式化写指令写入一条以上的记录。在此种情况下,会为随后的每一条记录赋予连续的记录号。

示例:直接访问、格式化、多记录写入

OPEN( 21, ACCESS=’DIRECT’, RECL=200, FORM=’FORMATTED’) WRITE(21,’(10F10.3)’,REC=11) (X(J),J=1,100)

写入直接访问单元 21 的写指令会创建 10 条记录,每条记录 10 个元素(因为格式指定每条记录 10 个元素),这些记录从 11 到 20 进行编号。

2.3 二进制 I/O

Sun Studio Fortran 95 扩展了 OPEN 语句,允许声明“二进制”I/O 文件。

使用 FORM=’BINARY’ 打开文件与使用 FORM=’UNFORMATTED’ 具有大致相同的效果,所不同的是文件中没有嵌入记录长度。如果没有此数据,则无法知道一条记录的开始或结束位置。因此,无法对 FORM=’BINARY’ 文件执行 BACKSPACE 操作,这是因为不知道要退格到什么位置。对 ’BINARY’ 文件执行 READ 操作时,将按需要读取尽可能多的数据来填充输入列表中的变量。

WRITE 语句:以二进制的形式将数据写入文件,并按输出列表中指定的数量传输字节。

READ 语句:将数据读取到输入列表中的变量,并传输该列表所要求数量的字节。因为文件中没有记录标记,所以不进行“记录结束”错误检测。检测到的唯一错误是“文件结束”或异常系统错误。

INQUIRE 语句:在使用 FORM="BINARY" 打开的文件中,INQUIRE 返回:FORM="BINARY" ACCESS="SEQUENTIAL" DIRECT="NO" FORMATTED="NO" UNFORMATTED="YES"RECL=NEXTREC= 没有定义。

BACKSPACE 语句:不允许使用-返回一个错误。

ENDFILE 语句:在当前位置照常截断文件。

REWIND 语句:将文件照常重新定位到数据的开头。

2.4 流 I/O

f95 中实现了 Fortran 2003 标准“流”I/O 的新方案 。流 I/O 访问将数据文件视作连续的字节序列,用从 1 开始的正整数来寻址。可用 OPEN 语句中的 ACCESS=’STREAM’ 说明符来声明流 I/O 文件。字节地址文件定位要求 READWRITE 语句中有 POS=scalar_integer_expression 说明符。INQUIRE 语句接受 ACCESS=’STREAM’、说明符 STREAM=scalar_character_variable 和 POS=scalar_integer_variable。

流 I/O 在与 C 程序创建或读取的文件进行互操作时非常有用,如下例所示:

Fortran 95 program reads files created by C fwrite() program reader integer:: a(1024), i, result open(file="test", unit=8, access="stream",form="unformatted") ! read all of a read(8) a do i = 1,1024 if (a(i) .ne. i-1) print *,’error at ’, i enddo ! read the file backward do i = 1024,1,-1 read(8, pos=(i-1)*4+1) result if (result .ne. i-1) print *,’error at ’, i enddo close(8) end C program writes to a file #include int binary_data[1024]; /* Create a file with 1024 32-bit integers */ int main(void) { int i; FILE *fp; for (i = 0; i < 1024; ++i) binary_data[i] = i; fp = fopen("test", "w"); fwrite(binary_data, sizeof(binary_data), 1, fp); fclose(fp); }

C 程序使用 C fwrite() 将 1024 个 32 位整数写入文件中。Fortran 95 读取程序以数组方式一次读取这些数据,然后再在文件中从后往前分别读取它们。第二条 read 语句中的 pos= 说明符说明位置是用字节表示的,从字节 1 开始(这一点与 C 相反,在 C 中,位置从字节 0 开始)。

2.5 内部文件

内部文件是 CHARACTER 类型的对象,如变量、子串、数组、数组元素或结构化记录的字段。内部文件 READ 可以来自常量字符串。内部文件 I/O 通过由一个字符对象向另一数据对象传送和转换数据,模拟格式化 READWRITE 语句。不执行任何文件 I/O。

使用内部文件时:

出现在 WRITE 语句中的是接收数据的字符对象的名称而非单元号。在 READ 语句中,出现的是字符对象源的名称而非单元号。

常量、变量或子串对象构成文件中的单条记录。

使用数组对象,每个数组元素对应于一条记录。

内部文件上的直接 I/O。(Fortran 95 标准只包括内部文件上的顺序格式化 I/O。)除了不能更改文件中的记录数之外,这一点与外部文件上的直接 I/O 相似。此时,记录是字符串数组的单个元素。这项非标准扩展仅在用 -f77 标志编译的 FORTRAN 77 兼容模式下可用。

每一顺序 READWRITE 语句均始于内部文件的开头。

示例:从内部文件(仅有一条记录)中以顺序、格式化方式进行读取:

demo% cat intern1.f CHARACTER X*80 READ( *, ’(A)’ ) X READ( X, ’(I3,I4)’ ) N1, N2 ! This codeline reads the internal file X WRITE( *, * ) N1, N2 END demo% f95 -o tstintern intern1.f demo% tstintern 12 99 12 99 demo%

示例:从内部文件(三条记录)中以顺序、格式化方式进行读取:

demo% cat intern2.f CHARACTER LINE(4)*16 DATA LINE(1) / ’ 81 81 ’ / DATA LINE(2) / ’ 82 82 ’ / DATA LINE(3) / ’ 83 83 ’ / DATA LINE(4) / ’ 84 84 ’ / READ( LINE,’(2I4)’) I,J,K,L,M,N PRINT *, I, J, K, L, M, N END demo% f95 intern2.f demo% a.out 81 81 82 82 83 83 demo%

示例:在 -f77 兼容模式下,从内部文件(一条记录)中以直接访问方式进行读取:

demo% cat intern3.f CHARACTER LINE(4)*16 DATA LINE(1) / ’ 81 81 ’ / DATA LINE(2) / ’ 82 82 ’ / DATA LINE(3) / ’ 83 83 ’ / DATA LINE(4) / ’ 84 84 ’ / READ ( LINE, FMT=20, REC=3 ) M, N 20 FORMAT( I4, I4 ) PRINT *, M, N END demo% f95 -f77 intern3.f demo% a.out 83 83 demo% 2.6 大端字节序和小端字节序平台之间的二进制 I/O

在 SPARC 和 x86 平台间移动时,新的编译器标志 -xfilebyteorder 支持二进制 I/O 文件。标志标识未格式化 I/O 文件的字节顺序和字节对齐。

例如,

-xfilebyteorder=little4:%all,big16:20

将指定所有文件(以 "SCRATCH" 打开的文件除外)包含 4 字节边界对齐(例如 32 位 x86)的“小端字节序”数据,Fortran 单元 20 除外,该单元是 64 位“大端字节序”文件(例如 64位 SPARC V9)。

有关详细信息,请参见 f95(1) 手册页或《Fortran 用户指南》。

2.7 传统 I/O 注意事项

Fortran 95 及传统 Fortran 77 程序在 I/O 上是兼容的。包含 f77f95 混合编译代码的可执行文件可以同时从程序的 f77f95 部分对同一单元执行 I/O 操作。

但是,Fortran 95 还提供了一些附加功能:

ADVANCE=’NO’ 允许进行非提前式 I/O 操作,如下所示:

write(*,’(a)’,ADVANCE=’NO’) ’Enter size= ’ read(*,*) n

NAMELIST 输入功能:

f95 允许输入时在组名前使用 $&。Fortran 95 标准只接受 &,并且这是 NAMELIST 写入语句的输出内容。

f95 接受 $ 作为输入组的终止符号,除非组中的最后一个数据项为 CHARACTER(在这种情况下,$ 被视为输入数据)。

f95 允许 NAMELIST 输入开始于记录的第一列。

正如 f77 所做的那样,f95 承认并实现了 ENCODEDECODE

有关 f95f77 间的 Fortran 95 I/O 扩展及兼容性方面的其他信息,请参见《Fortran 用户指南》。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3