You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fortran读取含字符串与数值的二进制文件问题求助

问题解答

核心结论

如果目标文件是文本头+无格式二进制数据的混合格式,确实需要调整文件打开方式来读取后续数值数组。Fortran无法在同一个打开的文件句柄下切换FORMATTED和UNFORMATTED模式,推荐两种可行方案:

方案1:分两次打开文件(先读文本,再读二进制)

先以FORMATTED模式读取7行文本头,记录文本结束后的字节位置,关闭文件后再以UNFORMATTED模式重新打开并定位到该位置,最后读取数组。

PROGRAM READ_MIXED_FILE
    IMPLICIT NONE
    INTEGER, PARAMETER :: NUM_HEADER = 7
    CHARACTER(LEN=256) :: header_line
    INTEGER :: fu, i, pos_after_header, arr_size
    REAL, ALLOCATABLE :: x(:), y(:), z(:)
    INTEGER, ALLOCATABLE :: int_arr(:)

    ! 读取文本头并记录结束位置
    OPEN(fu, FILE='target_file.bin', STATUS='OLD', ACTION='READ', FORM='FORMATTED')
    DO i = 1, NUM_HEADER
        READ(fu, '(A)') header_line
        ! 从文本头提取数组大小,示例:若某行含"ARR_SIZE: 1000"
        ! IF (INDEX(header_line, 'ARR_SIZE') /= 0) READ(header_line(INDEX(header_line,':')+2:), *) arr_size
    END DO
    INQUIRE(fu, POS=pos_after_header)
    CLOSE(fu)

    ! 以无格式模式打开并定位
    OPEN(fu, FILE='target_file.bin', STATUS='OLD', ACTION='READ', FORM='UNFORMATTED', ACCESS='STREAM')
    READ(fu, POS=pos_after_header)

    ! 调用读取子程序
    CALL READ_REAL_ARRAY(fu, arr_size, x)
    CALL READ_REAL_ARRAY(fu, arr_size, y)
    CALL READ_REAL_ARRAY(fu, arr_size, z)
    CALL READ_INT_ARRAY(fu, arr_size, int_arr)

    CLOSE(fu)
END PROGRAM

! 实型数组读取子程序
SUBROUTINE READ_REAL_ARRAY(unit, size, arr)
    INTEGER, INTENT(IN) :: unit, size
    REAL, ALLOCATABLE, INTENT(OUT) :: arr(:)
    ALLOCATE(arr(size))
    READ(unit) arr
END SUBROUTINE

! 整型数组读取子程序
SUBROUTINE READ_INT_ARRAY(unit, size, arr)
    INTEGER, INTENT(IN) :: unit, size
    INTEGER, ALLOCATABLE, INTENT(OUT) :: arr(:)
    ALLOCATE(arr(size))
    READ(unit) arr
END SUBROUTINE

方案2:用STREAM模式一次性打开(推荐)

STREAM模式支持直接按字节操作文件,无需切换打开模式,同时兼容文本和二进制数据的读取:

PROGRAM READ_MIXED_STREAM
    IMPLICIT NONE
    INTEGER, PARAMETER :: NUM_HEADER = 7
    CHARACTER(LEN=256) :: header_line
    INTEGER :: fu, i, arr_size
    REAL, ALLOCATABLE :: x(:), y(:), z(:)
    INTEGER, ALLOCATABLE :: int_arr(:)

    ! 以STREAM模式打开文件
    OPEN(fu, FILE='target_file.bin', STATUS='OLD', ACTION='READ', ACCESS='STREAM')

    ! 读取文本头
    DO i = 1, NUM_HEADER
        READ(fu, '(A)') header_line
        ! 提取数组大小
    END DO

    ! 直接读取二进制数组
    CALL READ_REAL_ARRAY(fu, arr_size, x)
    CALL READ_REAL_ARRAY(fu, arr_size, y)
    CALL READ_REAL_ARRAY(fu, arr_size, z)
    CALL READ_INT_ARRAY(fu, arr_size, int_arr)

    CLOSE(fu)
END PROGRAM

! 实型数组读取子程序(STREAM模式通用)
SUBROUTINE READ_REAL_ARRAY(unit, size, arr)
    INTEGER, INTENT(IN) :: unit, size
    REAL, ALLOCATABLE, INTENT(OUT) :: arr(:)
    ALLOCATE(arr(size))
    READ(unit) arr
END SUBROUTINE

! 整型数组读取子程序(STREAM模式通用)
SUBROUTINE READ_INT_ARRAY(unit, size, arr)
    INTEGER, INTENT(IN) :: unit, size
    INTEGER, ALLOCATABLE, INTENT(OUT) :: arr(:)
    ALLOCATE(arr(size))
    READ(unit) arr
END SUBROUTINE

关键注意事项

  • 数组大小arr_size必须准确,建议从文本头中提取(生成文件时应将数组大小写入头信息),否则会导致读取错误;
  • 若INQUIRE(POS=...)定位不准,可手动计算文本头总字节数(每行长度+换行符字节:Windows为2字节,Linux为1字节);
  • 读取模式必须与文件生成时的写入模式一致:如果数组是用FORM='UNFORMATTED'写入的,读取时必须用相同模式。

内容的提问来源于stack exchange,提问作者Moonwalk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:00:34