Fortran读取含多类型列的CSV文件失败,求解决方案
问题分析
你的读取失败核心有两个原因:
- Fortran默认的列表读取(
*格式符)以空格/制表符作为字段分隔符,不会识别CSV的逗号,导致逗号被当成数据的一部分,解析完全混乱。 - 第二列是
2013/02/20这类日期字符串,无法直接存入real类型数组,必须用字符类型存储,或者转换成数值格式(比如儒略日)。
解决方案
方案一:保留日期字符串,正确读取CSV
首先调整数据结构,适配不同类型的字段,再用显式格式控制指定逗号分隔符:
program read_csv implicit none integer, allocatable :: ids(:) character(len=10), allocatable :: dates(:) real, allocatable :: values(:) integer :: num_rows = 0, io, i ! 先统计文件行数,方便分配数组 open(10, file='data.csv', status='old', action='read') do read(10, *, iostat=io) if (io /= 0) exit num_rows = num_rows + 1 end do rewind(10) ! 分配对应长度的数组 allocate(ids(num_rows), dates(num_rows), values(num_rows)) ! 逐行读取,用格式符指定逗号分隔规则 do i = 1, num_rows read(10, '(I0, ",", A10, ",", F0.3)', iostat=io) ids(i), dates(i), values(i) if (io /= 0) then print *, "读取第", i, "行时出错" exit end if end do close(10) ! 验证读取结果 do i = 1, num_rows print *, ids(i), dates(i), values(i) end do end program read_csv
格式符(I0, ",", A10, ",", F0.3)的含义:
I0:自动适配宽度的整数类型,匹配第一列的序号",":明确匹配CSV的逗号分隔符A10:长度为10的字符类型,刚好对应YYYY/MM/DD格式的日期F0.3:自动适配宽度的实数类型,保留3位小数匹配第三列数值
如果想让数据结构更清晰,也可以用派生类型:
type :: csv_record integer :: id character(len=10) :: date real :: value end type csv_record type(csv_record), allocatable :: data(:)
方案二:将日期转换为数值类型
如果需要把日期用于数值计算,可以将字符串拆分成年、月、日整数,再转换成儒略日等数值格式:
do i = 1, num_rows character(len=10) :: date_str integer :: year, month, day read(10, '(I0, ",", A10, ",", F0.3)', iostat=io) ids(i), date_str, values(i) ! 从日期字符串中拆分年、月、日 read(date_str, '(I4, "/", I2, "/", I2)') year, month, day ! 这里可以添加儒略日或其他日期数值的计算逻辑 end do
额外注意事项
- 打开文件时指定
status='old'确保文件存在,action='read'明确只读权限,避免意外修改文件。 - 始终用
iostat捕获读取错误,方便定位具体哪一行数据出问题。 - 如果CSV字段长度不固定,可以把格式符中的
A10改成A,让Fortran自动匹配字符长度。
内容的提问来源于stack exchange,提问作者statsbeginner
相关产品推荐
相关产品推荐

