项目

一般

简介

行为

支持 #465

打开

Fortran 与 C++ 文件读写差异对比

李立奎4 天 之前添加. 更新于 3 天 之前.

状态:
新建
优先级:
普通
指派给:
-
开始日期:
2026-01-15
计划完成日期:
% 完成:

0%

预期时间:
#2:

描述

Fortran 与 C++ 文件读写差异对比

基于你熟悉的 C++ 背景,我来梳理 Fortran 文件读写的核心差异。两者在理念、语法和底层实现上都有显著不同。

一、核心概念差异

1. 文件标识方式

  • C++: 使用文件流对象(ifstream/ofstream)作为句柄,面向对象风格
  • Fortran: 使用整数单元号(UNIT)标识文件,过程式风格
    ! Fortran: 需手动指定单元号(通常>10)
    open(10, file="data.txt")
    read(10, *) x
    close(10)
    
    ! 现代Fortran2003+ 可用 newunit 自动分配
    integer :: u
    open(newunit=u, file="data.txt")
    

2. 编程范式

  • C++: 对象方法调用,如 file.open(), file.read(), file.close()
  • Fortran: 独立语句,如 OPEN, READ, WRITE, CLOSE

二、文件打开与关闭

打开参数对比

特性 C++ (fstream) Fortran (OPEN)
文件名 构造函数或 open() 参数 FILE='name' 参数
打开模式 ios::in, ios::out, ios::binary, ios::app 等位掩码组合 STATUS='old'/'new'/'replace', ACCESS='sequential'/'direct', ACTION='read'/'write'/'readwrite'
二进制模式 ios::binary 标志 FORM='unformatted' 参数
自动创建 ios::out 自动创建 STATUS='new''replace'

关键差异点

  1. 单元号 vs 对象: Fortran 必须用整数单元号,C++ 用对象实例
  2. 模式分离: Fortran 将访问方式(SEQUENTIAL/DIRECT)、格式(FORMATTED/UNFORMATTED)、动作(ACTION)分开指定,C++ 用位掩码组合

三、文本文件读写

1. 格式化I/O

  • C++: 使用 <<>> 运算符,自动类型推导

    file << x << " " << y << endl;
    file >> x >> y;
    
  • Fortran: 必须指定格式字符串或使用表控格式(*

    ! 指定格式(非常严格)
    write(10, '(I5, F10.3)') i, x
    
    ! 表控格式(类似C++的<<,但分隔符有差异)
    write(10, *) i, x
    read(10, *) i, x
    

2. 字符串差异

  • C++: std::string 是原生类型,支持动态长度
  • Fortran: CHARACTER(len=n) 必须预定义固定长度,读取时不会自动截断,可能导致空格填充

3. 行操作

  • C++: getline(file, str) 直接读整行
  • Fortran: 需用格式描述符 (A) 读取字符数组
    character(len=100) :: line
    read(u, '(A)') line  ! 读整行
    

四、二进制文件处理(核心差异)

1. 存储结构

这是最大差异

  • C++: 纯字节流,无额外元数据

    // 直接写入内存二进制映像
    file.write(reinterpret_cast<char*>(&data), sizeof(data));
    
  • Fortran: 记录式结构,每条记录前后有4字节长度标记(编译器相关)

    ! 顺序写入时,Fortran会添加头部和尾部长度记录
    open(u, file='data.bin', form='unformatted')
    write(u) data_array  ! 实际写入: [4字节长度][数据][4字节长度]
    

    后果: Fortran二进制文件通常只能用Fortran读取,跨语言兼容性差

2. 解决方案

  • 现代Fortran: 使用 access='stream' 模拟C++的字节流
    ! Fortran2003+ 支持,与C++二进制兼容
    open(newunit=u, file='data.bin', form='unformatted', access='stream')
    read(u) data
    

3. 直接访问模式

  • C++: 用 seekg()/seekp() 任意定位,配合 read()/write()

    file.seekg(100, ios::beg);  // 偏移100字节
    file.read(&data, sizeof(data));
    
  • Fortran: 用 ACCESS='direct' 指定固定记录长度

    ! 每条记录长度必须固定(RECL单位依赖编译器)
    open(u, file='data.bin', access='direct', recl=32)
    read(u, rec=5) data  ! 读取第5条记录
    

五、文件位置控制

操作 C++ Fortran
定位到开头 file.seekg(0) REWIND(u)
定位到末尾 file.seekg(0, ios::end) 无直接等价,需用 INQUIRE 查大小
相对偏移 file.seekg(offset, ios::cur) 无直接等价
获取当前位置 file.tellg() 无直接等价(流访问除外)
回退一条记录 无直接等价 BACKSPACE(u)

六、错误处理

  • C++: 状态位检查 file.good(), file.eof(), file.fail()
  • Fortran: IOSTAT=ERR= 标签
    read(u, *, iostat=ios) x
    if (ios /= 0) then
      ! 处理错误
    end if
    

七、其他重要差异

1. 预定义设备

Fortran 预定义单元号需避免:

  • * : 标准输入/输出(类似C++的 cin/cout
  • 5 : 键盘(输入)
  • 6 : 显示器(输出)

C++ 无此概念,直接使用 std::cin/std::cout

2. 默认行为

  • C++: 文本模式默认,换行符自动转换
  • Fortran: 格式化(FORMAT='formatted')默认,但对空格敏感,BLANK='null'/'zero' 影响数字读取

3. 跨平台换行

  • C++: << endl 自动写入系统换行符
  • Fortran: 每条 WRITE 语句默认换行,需用 ADVANCE='NO' 控制

八、混合编程建议

若需在C++和Fortran间交换二进制数据:

  1. Fortran端: 使用 access='stream' 避免记录标记
  2. C++端: 确保结构体/class 内存布局一致(注意填充字节)
  3. 推荐: 使用文本格式或HDF5/netCDF等跨语言标准格式

总结速查表

功能 C++ Fortran
打开 ifstream f("file.txt") open(u, file='file.txt')
读取整数 f >> x; read(u, *) x
写入整数 f << x; write(u, *) x
二进制读 f.read(buf, size); read(u) buf (需stream模式)
定位 f.seekg(pos); seek (仅direct/stream)
关闭 f.close(); close(u);

理解这些差异后,从C++转向Fortran文件操作,核心在于适应单元号格式字符串的显式管理,并特别注意二进制文件的记录结构问题。

行为

导出 Atom PDF