【Fortran】文件读取、写入(初级)


Fortran中的文件处理(初级)

简述

在Fortran程序中使用文件,需要一些选择所需文件和读写该文件的方法,该机制称为输入/输出单元I/O单元)。
READ(* , *)WRITE(* , *)语句中的第一个*号与 I/O单元 相对应。当*号被 I/O单元号 代替时,程序对应的读和写将指向该单元指定的设备,替代预定标准的输入或输出设备。

  • I/O单元号必须为整数类型;
  • I/O单元号5 预定义为程序的标准输入设备(即键盘),为 6 预定义为程序的标准输出设备(即显示器),此时用*号表示。

常用的语句有:

I/O 语句用途
OPEN将一个文件与一个给定的I/O单元号关联起来
CLOSE关闭一个文件并释放与之关联的I/O单元号
REWIND倒回文件,一般用于倒回临时文件

语句

1) OPEN
  1. 语句:OPEN( open_list ),其中open_list是一组子句,分别指定I/O单元号、文件名和关于如何存取文件的信息。特性:

    • 子句的顺序可以是任意;
    • 子句用逗号,隔开。
  2. open_list含有许多子句,最重要的主要有以下六项:

    1. UNIT = int_expression,指明与文件关联的I/O单元号,int_expression为非负的整数值;
    2. FILE = char_expression,指定要打开的文件名,char_expression为文件名称的字符值;
    3. STATUS = char_expression,指定要打开文件的状态,char_expression的取值为下列中的一个:OLDNEWREPLACESCRATCHUNKNOW
    4. ACTION = char_expression,指定文件以读或写的方式打开,char_expression的取值为下列中的一个:READWRITEREADWRITE,如未指定则是以读写方式打开;
    5. IOSTAT = int_variable,指定一个整数变量名,把打开操作的状态返回到这个int_variable变量中。如果OPEN语句成功执行,则整数变量int_variable的值为0,其它数值则是未成功执行(不同处理器,相应系统错误信息会不同);
    6. IOMSG = char_variable,指定一个字符变量名。如果OPEN语句成功执行,字符变量char_variable的内容不会变化,如没成功执行,一个描述错误的信息将返回到该字符串中。
2) CLOSE

语句:CLOSE( close_list )close_list必须包含一个指定I/O单元号的子句,还可以指定其它选项。特性:

  • 文件关闭后,相关联的I/O单元被释放,可以用OPEN将该单元号重新分配给其它任意文件;
  • 如果程序中没有包含对给定文件的CLOSE语句,这个文件将在程序结束时被自动关闭。
3) READ语句中添加子句

在使用READ语句时,可以添加IOSTAT = int_variableIOMSG = char_variable子句,检查是否发生读取错误,并返回相应信息,而不引起程序异常中断

  1. IOSTAT = int_variable

    • READ语句成功执行时,int_variable的值为0;
    • READ语句执行失败,如读取的变量不符合所定义类型时,int_variable的值为与系统错误信息相对应的正数;
    • READ语句执行至数据文件的尾部时,语句会执行失败,int_variable的值为负数。
  2. IOMSG = char_variable,当IOSTAT变量值为非0时,IOMSG会已语句形式返回字符串来解释发生的错误。

注意:当从文件中读取数据时,READ语句应总是包含IOSTAT子句,使得程序可以检查所读取的数据是否符合要求(如类型判断),以及避免读取文件结尾之外行信息时的异常中断。

  1. 具体例子:现有一个数据文件,有多行,每一行中有1个数据,数据类型是实数型,通过输入文件名来获取其中的数据,输出内容为实数数据及其对应行号,并交代总行数(即数据个数)。同时,需要能够返回数据读取失败时的信息提醒,以及文件打开错误时的信息提醒。
    代码如下:

    PROGRAM read_file
    IMPLICIT NONE
    CHARACTER(len = 20)::filename    ! 文件名称
    CHARACTER(len = 80)::msg          ! 打开文件错误时的异常信息
    INTEGER::nvals = 0                       ! 读取数据的行数
    INTEGER::status1 , status2            ! 打开文件和读取数据的状态信息
    REAL::value                                   ! 需读取文件中的数据
    
    WRITE(*,*) 'Please enter input file name'    ! 读取需要打开的文件
    READ(*,*) filename
    WRITE(*,1000) filename
    1000 FORMAT('The input file name is: ' , A)
    
    OPEN(UNIT = 3 , FILE = filename , STATUS = 'OLD' , ACTION = 'READ' , IOSTAT = status1 , IOMSG = msg)  ! 打开文件
    
    openif:IF(status1 == 0 ) THEN    ! 文件打开成功
        readloop:DO
        READ(3 , * , IOSTAT = status2) value
        IF(status2 /= 0) EXIT      ! 如果数据读取失败,跳出DO循环
        nvals = nvals + 1
        WRITE(*,1010) nvals,value
        1010 FORMAT('Line ',I6,' :Value = ',F10.4)
        END DO readloop
        readif:IF(status2 > 0) THEN      ! 发生了数据读取错误
            WRITE(*,1020) nvals+1
            1020 FORMAT('An error occurred reading line ',I6)        ! 交代在哪一行读取数据失败
            ELSE readif     ! 到达数据结尾
            WRITE(*,1030) nvals
            1030 FORMAT('End of file reached.There were ' , I6 , ' values in the file.')   ! 交代已经到达文件结尾
        END IF readif
    ELSE openif         ! 文件打开失败
        WRITE(*,1040) status1
        1040 FORMAT('Error opening file : IOSTAT = ',I6)
        WRITE(*,1050) TRIM(msg)   ! 返回错误信息
        1050 FORMAT(A)   
    END IF openif
    
    CLOSE(UNIT = 3)     ! 关闭文件
    
    STOP 
    END PROGRAM read_file
    

    现有正确的数据文件read1.txt和错误的数据文件read2.txt,内容分别是:

    ! read1.txt
    -15.0  
    55.333
    9.0
    4444.
    -0.02
    

    ! read2.txt
    -15.0  
    55.333
    9.0
    abc
    -0.02
    

    运行程序,并分别输入read1.txtread2.txtabc.txt可得:

    Please enter input file name
    read1.txt
    The input file name is: read1.txt
    Line      1 :Value =   -15.0000
    Line      2 :Value =    55.3330
    Line      3 :Value =     9.0000
    Line      4 :Value =  4444.0000
    Line      5 :Value =    -0.0200
    End of file reached.There were      5 values in the file.  ! 提示到达数据文件的底部,成功
    
    Please enter input file name
    read2.txt
    The input file name is: read2.txt
    Line      1 :Value =   -15.0000
    Line      2 :Value =    55.3330
    Line      3 :Value =     9.0000
    An error occurred reading line      4  ! 提示第4行数据不满足要求
    
    Please enter input file name
    abc.txt            ! 输入不存在的文件
    The input file name is: abc.txt
    Error opening file : IOSTAT =     29
    file not found, unit 3, file E:\ProgramData\test\abc   ! 返回错误信息,说明该文件abc不存在
    
4) 文件定位

Fortran提供两条语句,帮助在顺序文件内容来回移动:

  • BACKSPACE,每次调用都会回退一条记录;

  • REWIND,倒回文件,可以从文件首部重新开始,可用于倒回临时文件,如下例所示:

    PROGRAM scratch_file
    IMPLICIT NONE
    INTEGER,PARAMETER::LU = 8   ! 临时文件I/O单元号
    REAL:: data1
    INTEGER::icount = 0
    INTEGER::irecord
    INTEGER::j
    
    OPEN(UNIT = LU , STATUS = 'SCRATCH' )  ! 创建临时文件,状态为SCRATCH表示创建临时文件,此时不能指定具体文件名
    WRITE(*,*) 'Enter positive or zero input values. A negative value terminates input.'  
    
    readloop:DO    ! 用于往临时文件中输入数据
        WRITE(*,110) icount +1
    110    FORMAT('Enter sample ',I4,' : ')
        READ(*,*) data1
        IF(data1 < 0.) EXIT
        icount = icount + 1
        WRITE(LU , 120) data1  ! 将数据以科学级数法形式写入临时文件中
    120 FORMAT(ES16.6)
    END DO readloop
    
    WRITE(*,130) icount     ! 提示可以读取临时文件中的数据,并显示范围
    130 FORMAT('Which record do you want to see(1 to ',I4,' )? ')
    READ(*,*) irecord
    
    record_data:IF((irecord >= 1).AND.(irecord <= icount)) THEN   ! 满足irecord的要求时
        REWIND(UNIT = LU)    ! 回倒临时文件
        DO j = 1,irecord       ! 对每一行数据进行遍历,直到结束,而结束时即为要查询的irecord(位置),然后输出相应数值
            READ(LU,*) data1
        END DO
        WRITE(*,140) irecord,data1
    140 FORMAT('The value of record ' , I4 , ' is ' , ES12.5)
    ELSE record_data
        WRITE(*,150) irecord      ! 如果不满足irecord要求,返回错误信息
    150 FORMAT('Illegel record number entered:',I8)
    END IF record_data
    
    CLOSE(UNIT = LU)
    END PROGRAM scratch_file
    

    相应结果为:

    Enter positive or zero input values. A negative value terminates input.
    Enter sample    1 :
    12.0     ! 键盘输入,以下同理
    Enter sample    2 :
    23.
    Enter sample    3 :
    66666
    Enter sample    4 :
    8884.2253
    Enter sample    5 :
    666.22
    Enter sample    6 :
    -8       ! 输入结束
    Which record do you want to see(1 to    5 )?   ! 倒回输入的数据中寻找
    4
    The value of record    4 is  8.88423E+03
    
  • 42
    点赞
  • 165
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值