读取列具有特定格式的文本文件

Read text file where the columns have specific format

我正在使用 Fortran,我需要读取一个包含 3 列的文件。问题是第 3 列是整数的组合,例如120120101,我需要将每个值分隔在不同的列中。

通常,我手动删除前 2 列,这样文件看起来像:

Info
0120012545
1254875541
0122110000
2254879933

要读取每个值都在不同列中的文件,我可以使用以下 Fortran 子例程:

subroutine readF(imp, m, n)
  implicit none
  integer :: n,m,i,imp(n,m)
  open(unit=100, file='file.txt', status='old', action='read')
  do i=2,n
    read(100,'(*(i1))') imp(i,1:m)
    end do
  close(unit=100)
end subroutine readF

不知是否可以读取如下内容的文件:

IDs Idx Info
ID001 1 125478521111
ID002 1 525478214147
ID003 2 985550004599
ID004 2 000478520002

结果如下:

ID001 1 1 2 5 4 7 8 5 2 1 1 1 1
ID002 1 5 2 5 4 7 8 2 1 4 1 4 7
ID003 2 9 8 5 5 5 0 0 0 4 5 9 9
ID004 2 0 0 0 4 7 8 5 2 0 0 0 2

第 3 列中的值出现在 m 列中。

第一行是header,但我不需要,所以我从第二行开始看。

我尝试编写使用以下子例程,但没有成功:

subroutine readF(imp, ind, m, n)
  implicit none
  integer :: n,m,i,imp(n,m),ind(n),chip(n)
  open(unit=100, file='file.txt', status='old', action='read')
  do i=2,n
    read(100,'(i8,i1,*(i1))') ind(i),chip(i),imp(i,1:m)
  end do
  close(unit=100)
end subroutine readF

有谁知道我如何在不手动删除前两列的情况下读取该文件?

谢谢。

我将猜测每个变量的含义,并尝试解释一些明显的错误。

我认为你的 do i=2,n 是个错误,因为我看到我的一些学生犯过这个错误。从 2 开始 i 并不意味着您正在从第二行开始阅读,它只是 i 的值。然后,假设您有 n 条数据线,您将错过最后一条数据线,因为您正在读取 n-1 行。您想要的是循环之前的空白读取语句。这将跳过 header 行。然后你想让我从1到n。

从读取语句中变量的顺序来看,我假设ind是ID号,chip是Idx号,imp的Info号是1每个整数最多 m 个。

您的 i8 将获取前 8 列信息并尝试将它们解释为整数。嗯,ID001 1 1 是第一行数据的前 8 列,这不是整数。您需要跳过 'ID' 并将“001”读入 ind。然后跳过 1 个字符并将 1 个整数读入芯片,然后再跳过 1 个字符然后读入信​​息,一次读入 1 个整数。 x 格式说明符跳过 1 个字符。

对于要分别进入 imp 的每个整数,您需要一个从 1 到 m 的隐式 do 循环。我在那里用 j 。如果您不知道隐含的 do 循环,请 google 它。这在 Fortran 中是相当标准的。

此代码段将执行此操作:

open(unit=100, file='file.txt', status='old', action='read')
read(100,*)  ! This skips the header line.
do i=1,n     ! Read in n data lines.
  read(100,'(2x,i3,1x,i1,1x,*(i1))') ind(i),chip(i),(imp(i,j),j=1,m)
end do
close(unit=100)

解决评论的其他答案。我知道你有两个选择。首先,进入行解析。我不会选择这个。

第二个选项是使用未格式化的输入来读取行。无格式输入使用空格来分隔输入项。我将使第三项成为一个足够长的字符变量,以容纳 m 的长度。这个字符变量可以用 Fortran 的 read 语句读取。这称为从内部记录读取。您将像以前一样读取每个整数。这就是它的样子:

character(len=m) :: Info
character(len=:),allocatable :: Dumb
open(unit=100, file='file.txt', status='old', action='read')
read(100,*)  ! This skips the header line.
do i=1,n     ! Read in n data lines.
  read(100,*) Dumb, chip(i), Info
  read(Info,'(*(i1))') (imp(i,j),j=1,m)
end do
close(unit=100)

do 循环中的第一个读取语句是从文件中读取。它将整个第一列粘贴到 Dumb 中,无论其长度如何,第二列粘贴到 chip(i) 中,整个第三列粘贴到一个名为 Info.

的字符串中

第二条读取语句是从 "internal record" 信息中读取。您可以在字符串上使用 read 语句。在这里,我使用格式说明符和隐含的 do 循环一次提取 1 个整数。