读取列具有特定格式的文本文件
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 个整数。
我正在使用 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 个整数。