Fortran--阅读具有特定时间戳的列

时间:2015-11-26 09:21:37

标签: fortran

我有这个数据集,我想用Fortran阅读它并应用一些操作。我已经提供了下面的数据集。这是对数据集的简短描述。数据集以时间戳开始,随后的行(约60或120)是此时记录的数据点,后面再跟着时间戳和数据,依此类推。每个文件有大约30个观测值,有15个不同的时间戳(即两个相邻的观测值具有相同的时间戳)。我现在想读取这个文件,并使用相同的时间戳执行诸如在数据点上添加或减少列的操作。

这里' 6:31:5',' 6:27:9'是数据后跟的时间戳。

请帮忙,因为我无法找到办法。 非常感谢你。

Here the '6:31: 5' is the time stamp followed by the data

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:1)

你的问题留下了很多含糊之处。我理解它的方式是你想要读取一个文件,其中一行的内容可能是两个不同的东西之一:一个值或一个时间戳。

在你阅读它之前,你不知道它是哪一个。

我认为最好的方法是首先将该行读入字符串。

character(len=20) :: line
read(1001, '(A)') line

然后,根据该字符串中的第一个字符,您可以推断出它是哪一个。

if (line(1:1) == "'") then
    ! It's a time stamp
else
    ! It's a new value
end if

如果它是一个值,你可以直接从行变量中读出它:

read(line, *) val

阅读时间戳更复杂,因为我不太清楚冒号在里面的位置。如果小时数都是一位数,你就可以得到类似的东西:

read(line, '(X, I1, X, I2, X, I2)') hour, minute, second

但是因为有几个小时不能用一个数字写,所以我很怀疑。

所以我建议您创建一个使用INDEX函数定位冒号的子例程,然后对该行进行切片以分别读取每个值。

hm = index(line, ':', back=.FALSE.) ! hour-minute separator
ms = index(line, ':', back=.TRUE.)  ! minute-second separator
read(line(2:hm-1), *) hour
read(line(hm+1:ms-1), *) minute
read(line(ms+1:), *) second

全部放在一起:

program timestamp
    implicit none
    integer, parameter :: runit = 1001
    integer :: io_err
    character(len=20) :: line
    real :: val
    integer :: hour, minute, second

    open(unit=runit, file='data.txt', action='READ', status='OLD', iostat=io_err)
    if (io_err /= 0) then
        write(*, *) "Unable to open file"
        stop 1
    end if

    do
        read(runit, '(A)', iostat=io_err) line
        if (io_err == -1) then
            write(*, *) "End of file"
            exit
        end if
        if (line(1:1) == "'") then
            call read_timestamp(line, hour, minute, second)
            write(*, '(A, 2(I2.2, ":"), I2.2)') "New timestamp: ", hour, minute, second
        else
            read(line, *) val
            write(*, *) "Data: ", val
        end if
    end do
    close(runit)

contains

    subroutine read_timestamp(line, hour, minute, second)
        implicit none
        character(len=*), intent(in) :: line
        integer, intent(out) :: hour, minute, second
        integer :: hm, ms ! Indices of separators
        hm = index(line, ':', back=.FALSE.)
        ms = index(line, ':', back=.TRUE.)
        read(line(2:hm-1), *) hour
        read(line(hm+1:ms-1), *) minute
        read(line(ms+1:), *) second
        return
    end subroutine read_timestamp
end program timestamp