1.7. 文件输入输出
Fortran 拥有丰富且易用的文件 I/O 能力,尤其擅长处理格式化表格数据。
1.7.1. 文件操作基础
1.7.1.1. 核心步骤
1. 打开文件(open 语句) → 分配通道号
2. 读写文件(read / write 语句)
3. 关闭文件(close 语句)
program file_demo
implicit none
integer :: unit
! 打开文件
open(newunit=unit, file="data.txt", status="unknown")
! 读写操作...
! 关闭文件
close(unit)
end program
1.7.1.2. 文件通道号
integer :: unit
! 方式 1:手动指定(传统)
open(unit=10, file="data.txt")
! 方式 2:newunit(Fortran 2003+,推荐)
! 自动分配未使用的通道号
open(newunit=unit, file="data.txt")
write(*, *) "通道号:", unit
close(unit)
小技巧
始终使用 newunit——它自动选择可用的通道号,避免冲突。
1.7.2. open 语句
! 基本格式
open(unit, file, status, action, position, iostat, errmsg)
! 实际示例
integer :: unit, ios
character(256) :: err_msg
open(newunit=unit, file="result.dat", status="replace", &
action="write", iostat=ios, iomsg=err_msg)
if (ios /= 0) then
write(*, *) "打开失败:", trim(err_msg)
stop
end if
1.7.2.1. status 参数
status |
含义 |
文件存在 |
文件不存在 |
|---|---|---|---|
|
读取已有文件 |
正常打开 |
出错 |
|
创建新文件 |
出错 |
创建 |
|
替换已有文件 |
清空重新创建 |
创建新文件 |
|
临时文件 |
(关闭时自动删除) |
创建临时文件 |
|
由编译器决定 |
正常打开 |
创建 |
1.7.3. 文本文件读写
1.7.3.1. 写入
integer :: i, unit
real :: x
open(newunit=unit, file="output.txt", status="replace", action="write")
! 自由格式写入
write(unit, *) "Hello, Fortran!", 42, 3.14
! 格式化写入
do i = 1, 10
x = i * 1.5
write(unit, '(I5, F10.3)') i, x
end do
close(unit)
! 标准输出:unit = 6 或使用 *
write(*, *) "输出到屏幕" ! * 表示标准输出
write(6, *) "同上"
1.7.3.2. 读取
integer :: i, unit, ios
real :: x
open(newunit=unit, file="input.txt", status="old", action="read")
! 逐行读取
do
read(unit, *, iostat=ios) i, x
if (ios /= 0) exit ! 文件结束或出错
write(*, *) i, x
end do
close(unit)
小心
read(..., iostat=ios) 检查 I/O 状态:
- ios == 0:正常
- ios < 0:文件结束 (EOF)
- ios > 0:发生错误
1.7.4. 格式化描述符
integer :: i = 42
real(8) :: x = 3.14159265358979_dp
character(10) :: name = "Fortran"
! 各格式示例
write(*, '(I5)') i ! " 42" (整数, 宽 5)
write(*, '(I0)') i ! "42" (I0 = 紧凑输出)
write(*, '(F8.3)') real(i) ! " 42.000" (浮点, 总宽8, 小数3)
write(*, '(E12.4)') x ! "0.3142E+01" (科学计数)
write(*, '(ES12.4)') x ! " 3.1416E+00" (现代科学计数)
write(*, '(A)') name ! "Fortran"
write(*, '(A10)') name ! " Fortran" (右对齐, 宽10)
write(*, '(L1)') .true. ! "T"
write(*, '(1X, A)') name ! 前导空格
! 组合格式
write(*, '(A, I0, A, F8.3)') "i=", i, ", x=", x
描述符 |
含义 |
示例输出 |
|---|---|---|
|
整数,宽度 w |
|
|
整数,紧凑格式 |
|
|
浮点,总宽 w,小数 d 位 |
|
|
科学计数 |
|
|
现代科学计数(推荐) |
|
|
字符串 |
|
|
逻辑值(T/F) |
|
|
空格 |
|
|
换行 |
|
1.7.5. namelist(命名列表)
Fortran 特有的强大功能:按名称读写变量组。
program namelist_demo
implicit none
integer :: n = 100
real :: tol = 1e-6_dp
logical :: debug = .false.
character(50) :: method = "RK4"
! 定义 namelist
namelist /params/ n, tol, debug, method
! 写入
open(10, file="params.nml", status="replace")
write(10, nml=params)
close(10)
! 读取(可修改部分参数,不要求全部提供)
n = 0; debug = .true.
open(10, file="params.nml", status="old")
read(10, nml=params)
close(10)
write(*, *) n, tol, debug, method
end program
生成的 params.nml 文件内容:
&PARAMS
N=100,
TOL=0.100000000000000E-005,
DEBUG=F,
METHOD="RK4",
/
小技巧
Namelist 非常适合**配置文件**: - 可读性强,易于手工编辑 - 可选择性修改部分参数 - 无需关心格式描述符
1.7.6. 二进制文件
integer, parameter :: n = 100
real(8) :: data(n)
integer :: unit
! 初始化
data = [ (i * 1.0_dp, i = 1, n) ]
! 写二进制文件
open(newunit=unit, file="data.bin", &
form="unformatted", status="replace", &
access="stream") ! 流式访问(推荐)
write(unit) data
close(unit)
! 读取
open(newunit=unit, file="data.bin", &
form="unformatted", status="old", access="stream")
read(unit) data
close(unit)
备注
access="stream" (Fortran 2003+) 以字节流方式读写,与 C 兼容。
传统方式使用 access="sequential" 或 access="direct"。
1.7.7. 文件操作常用函数
integer :: ios, unit
logical :: exists
! 检查文件是否存在
inquire(file="data.txt", exist=exists)
! 检查文件是否已打开
inquire(file="data.txt", opened=exists, number=unit)
! 获取文件大小
inquire(file="data.txt", size=ios)
! 检查读写状态
inquire(unit=10, iostat=ios)
! 删除文件
open(unit=10, file="temp.txt") ! 先打开
close(10, status="delete") ! 关闭时删除