如何解决“列表定向 I/O 语法错误”在 Fortran90 中读取 .CSV 文件时?

发布于 2025-01-15 04:48:23 字数 10650 浏览 0 评论 0原文

我假设我已经阅读了很多关于这个问题的问题,但我无法解决它。 在读取 .csv 文件期间,出现以下错误: forrtl:严重 (59):列表定向 I/O 语法错误,单元 10,文件 D:\OneDrive\MSc_Thesis\Projects\NEOs_orbits - TEST\InputFiles\test_Ast.csv。它似乎是由下面附加的 .csv 文件的特定行(最后一个)生成的。

这是我的 .CSV 文件:

"pdes","name","epoch","a","e","i","om","w","ma","q","ad"
1580,Betulia,2459600.5,2.197288160959855,.4871550690589618,52.07925829047207,62.2921305585828,159.5134530240992,16.62891169416756,1.126868095165017,3.267708226754692
1620,Geographos,2459600.5,1.245689288381319,.3353623816094239,13.33753650294321,337.1849253204765,276.9463790166408,300.4925456829043,.8279319618844114,1.663446614878227
1627,Ivar,2459600.5,1.86327342970777,.3967369932313492,8.451956512766827,133.120308337423,167.8035837640704,129.0289785125129,1.124043931637646,2.602502927777894
1685,Toro,2459600.5,1.367465568905196,.435966790549019,9.382739662870495,274.2362441040706,127.2114688956593,300.0617970060148,.7712959936433091,1.963635144167082
1862,Apollo,2459600.5,1.470502475713431,.5600430467767759,6.353083928279622,35.56898244993719,286.0386669340027,60.20237527657879,.6469577889220891,2.294047162504772
1863,Antinous,2459600.5,2.25922922966352,.6059920366929147,18.39886422664638,346.4237098245764,268.0896471241496,244.0101430178307,.8901543074235589,3.628304151903481
1864,Daedalus,2459600.5,1.460979692497998,.6144866009907846,22.21536437289675,6.613194571694206,325.6563726287792,196.1166696228387,.5632272471383416,2.358732137857654
1865,Cerberus,2459600.5,1.079986459127503,.4669721847798676,16.09858904525619,212.8963846822369,325.2653260753237,170.2073771841984,.57566282277606,1.584310095478947
1866,Sisyphus,2459600.5,1.893353802479725,.5383695942642949,41.20637430558688,63.47259682927852,293.0824330786623,331.1476239661798,.8740296840399557,2.912677920919495
1915,Quetzalcoatl,2459600.5,2.543790754476287,.5706410666538692,20.40472660837776,162.9348721741076,347.8091351438147,41.39145147165023,1.092199284997688,3.995382223954886
1916,Boreas,2459600.5,2.272324177667199,.4498393843780145,12.88297395642586,340.5981620510102,335.9167764123868,352.2401366045371,1.250143268478108,3.294505086856289
1917,Cuyo,2459600.5,2.14981121226236,.5054666607865446,23.95922692157032,188.2869783127825,194.5115030151171,82.2843922810623,1.063153317478631,3.236469107046088
1943,Anteros,2459600.5,1.430366783173011,.2560374828122278,8.706034969532251,246.3110706020363,338.3801329232052,173.8814283992249,1.064139272511169,1.796594293834852
1980,Tezcatlipoca,2459600.5,1.709370985747121,.3648359123967504,26.8689695764886,246.560199388918,115.4661353995156,314.1597421163634,1.085731062537538,2.333010908956705
1981,Midas,2459600.5,1.776435963774881,.6501354173857774,39.82986428861084,356.8569898560586,267.8286153975083,202.5329806814936,.621512027006993,2.931359900542769
2059,Baboquivari,2459600.5,2.64324121274608,.531432311471031,11.02055447003622,200.6851159860844,192.4190577597405,181.8930083473287,1.23853742528094,4.04794500021122
2061,Anza,2459600.5,2.264279343476608,.5360981217114927,3.800349706160866,207.3741353983842,157.0286649770264,354.1526556258232,1.050403440408666,3.478155246544549
2062,,2459600.5,.9669087478156669,.1827720931291991,18.9345273941421,108.5428491298942,148.0586126391113,21.46549438015371,.7901848121124645,1.143632683518869
"1979 XB",,2444221.5,2.228085656329666,.7084495059291489,24.73412122397795,86.0555030947377,75.57989828051527,346.3183743701075,.6495994739350907,3.806571838724241
594913,'Aylo'chaxnim,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162

这是我的 Fortran 程序(它包含一个主文件和一些模块):

program Main_NEOs_orbits_TEST

    use DataType
    use Constants
    use DataHandling
 
    implicit none   
    
    ! Declarations
    character*100 :: input_path,output_path_ast_EM_loc, input_filename_ast,input_filename_cmt, output_path, output_filename_ast
    character*118 :: str_line
    character*2   :: str_name
    character*30, dimension (3) :: str_output    
    integer :: i,j,iflag, no_data_lines1,n_lines2, iReturn, num_orb_elem
    type(NEO), dimension (:), allocatable :: Ast_data  
  
    
    ! Definition of constants, paths names and file names
    input_path = 'D:\OneDrive\MSc_Thesis\Projects\NEOs_orbits - TEST\InputFiles\'
    input_filename_ast = 'test_Ast.csv'

        
    ! Reading of asteroids data
    call read_NEOs_data(iu_in1, input_path, input_filename_ast, no_data_lines1, Ast_data)          

    stop

end program Main_NEOs_orbits_TEST
 
**********************************************************************************************************************************************

module Constants

    use DataType

    implicit none

    real(pr), parameter :: ZERO = 0.0_pr, ONE = 1.0_pr, TWO = 2.0_pr, THREE = 3.0_pr, FOUR = 4.0_pr, SEVEN = 7.0_pr 
    real(pr), parameter :: HALF = 0.5_pr, QUART = 0.25_pr
    real(pr), parameter :: DAY = 86400.0_pr, YEAR = 365.25_pr*DAY, CENTURY =  36525.0_pr
    real(pr), parameter :: KILO = 1000.0_pr
    real(pr), parameter :: AU2Km = 149597870.700_pr  ! (from Astronomicals Unit to kilometers)
    
    real(pr), parameter :: tol = 1.e-9_pr
    real(pr), parameter :: xmu = 1.32712440018e11_pr ! (km^3 * s^-2) xmu = G * M_Sun https://ssd.jpl.nasa.gov/astro_par.html
    
    ! Unit number for files
    integer :: iu_in1 = 10   !input file
    integer :: iu_in2 = 11   !input file
    integer :: iu_out1 = 12  !output file
    integer :: iu_out2 = 13  !output file
    
end module Constants

**********************************************************************************************************************************************
module DataHandling
    
    use DataType
    
    implicit none
    
    contains 

    !***********************************************************************
    subroutine read_NEOs_data(UnitNum, FilePath, FileName, DataLinesNum, NEOs_data)
    !***********************************************************************
    ! Subroutine for reading of asteroids database 
    !***********************************************************************
    !  INPUT:

    !
    !  OUTPUT:

    !***********************************************************************
        implicit none
    
        ! Arguments
        integer, intent (in) :: UnitNum
        character (len=*), intent (in) :: FilePath
        character (len=*), intent (in) :: FileName
        integer, intent (out) :: DataLinesNum
        type(NEO), dimension (:), allocatable, intent(out) :: NEOs_data
      
        !Local variables
        integer :: i, iflag
        
        
        open(unit = UnitNum, file = trim(FilePath) // trim(FileName), status='old', & 
                access = 'sequential',form = 'formatted', action='read')
    
            ! Count lines 
            DataLinesNum = 0
            read(UnitNum,*)  ! Header line
            do     
                read(UnitNum,*,iostat = iflag)
                if (iflag/=0) exit
                DataLinesNum =  DataLinesNum + 1
            enddo
         
            rewind(UnitNum)
    
            ! Variables allocation
            allocate(NEOs_data(DataLinesNum))
        
            ! Data reading 
            read(UnitNum,*)   ! skip header line (variables names will be assigned again)
            do i = 1, DataLinesNum
                read(UnitNum,*) NEOs_data(i)         
            enddo
        
        close(unit = UnitNum, status='keep') 
        
        return

    end subroutine read_NEOs_data
    !***********************************************************************
 
end module DataHandling   

**********************************************************************************************************************************************
module DataType

    implicit none

    integer, parameter :: pr = selected_real_kind (p = 15)  ! original value (p = 14) 
    
    !"NEO" data type declaration 
    type  NEO                       !  NEOs data :
        character*20 :: pdes        !  pdes      Object primary designation
        character*20 :: name        !  IAU name  Object IAU name
        real(pr) :: epoch           !  Epoch     Epoch Julian Date (TDB)
        real(pr) :: a               !  a         Semi-major axis (au)
        real(pr) :: e               !  e         Eccentricity       
        real(pr) :: i               !  i         Inclination w.r.t. xy-plane (deg)
        real(pr) :: om              !  om        Longitude of Ascending Node (deg)
        real(pr) :: w               !  w         Argument of Perihelion wrt to ecliptic/equinox (deg)
        real(pr) :: ma              !  ma        Mean anomaly (deg)
        real(pr) :: q               !  q         Perihelion distance (au)
        real(pr) :: ad              !  ad        Aphelion distance (au)
    end type NEO                    
    
end module DataType

我需要维护 .csv 文件的格式,所以我无法修改它。 你能解释一下为什么这条线: 594913,'Aylo'i ,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.7049822452751 68,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162产生上述错误?

错误输出:

forrtl: severe (59): list-directed I/O syntax error, unit 10, file D:\OneDrive\MSc_Thesis\Projects\NEOs_orbits - TEST\InputFiles\test_Ast.csv
Image              PC                Routine            Line        Source
libifcoremdd.dll   00007FFE5DBBAA5D  Unknown               Unknown  Unknown
libifcoremdd.dll   00007FFE5DC1B6FC  Unknown               Unknown  Unknown
NEOs_orbits_TEST.  00007FF75BB41B9B  DATAHANDLING_mp_R          53  DataHandling.f90
NEOs_orbits_TEST.  00007FF75BB43072  MAIN__                     57  Main_NEOs_orbits_TEST.f90
NEOs_orbits_TEST.  00007FF75BB4332E  Unknown               Unknown  Unknown
NEOs_orbits_TEST.  00007FF75BB45F69  Unknown               Unknown  Unknown
NEOs_orbits_TEST.  00007FF75BB45E8E  Unknown               Unknown  Unknown
NEOs_orbits_TEST.  00007FF75BB45D4E  Unknown               Unknown  Unknown
NEOs_orbits_TEST.  00007FF75BB45FDE  Unknown               Unknown  Unknown
KERNEL32.DLL       00007FFF269C7034  Unknown               Unknown  Unknown
ntdll.dll          00007FFF288A2651  Unknown               Unknown  Unknown

第 53 行:read(UnitNum,*) NEOs_data(i) 第 57 行:call read_NEOs_data(iu_in1, input_path, input_filename_ast, no_data_lines1, Ast_data)

有问题的行: 594913,'Aylo'chaxnim,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6。 704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162

I premise I've read many questions about this problem but I cannot solve it.
During the reading of my .csv file I get the following error:
forrtl: severe (59): list-directed I/O syntax error, unit 10, file D:\OneDrive\MSc_Thesis\Projects\NEOs_orbits - TEST\InputFiles\test_Ast.csv. It seems to be produced by a specific line of my .csv file attached beloew (the last one).

Here is my .CSV file:

"pdes","name","epoch","a","e","i","om","w","ma","q","ad"
1580,Betulia,2459600.5,2.197288160959855,.4871550690589618,52.07925829047207,62.2921305585828,159.5134530240992,16.62891169416756,1.126868095165017,3.267708226754692
1620,Geographos,2459600.5,1.245689288381319,.3353623816094239,13.33753650294321,337.1849253204765,276.9463790166408,300.4925456829043,.8279319618844114,1.663446614878227
1627,Ivar,2459600.5,1.86327342970777,.3967369932313492,8.451956512766827,133.120308337423,167.8035837640704,129.0289785125129,1.124043931637646,2.602502927777894
1685,Toro,2459600.5,1.367465568905196,.435966790549019,9.382739662870495,274.2362441040706,127.2114688956593,300.0617970060148,.7712959936433091,1.963635144167082
1862,Apollo,2459600.5,1.470502475713431,.5600430467767759,6.353083928279622,35.56898244993719,286.0386669340027,60.20237527657879,.6469577889220891,2.294047162504772
1863,Antinous,2459600.5,2.25922922966352,.6059920366929147,18.39886422664638,346.4237098245764,268.0896471241496,244.0101430178307,.8901543074235589,3.628304151903481
1864,Daedalus,2459600.5,1.460979692497998,.6144866009907846,22.21536437289675,6.613194571694206,325.6563726287792,196.1166696228387,.5632272471383416,2.358732137857654
1865,Cerberus,2459600.5,1.079986459127503,.4669721847798676,16.09858904525619,212.8963846822369,325.2653260753237,170.2073771841984,.57566282277606,1.584310095478947
1866,Sisyphus,2459600.5,1.893353802479725,.5383695942642949,41.20637430558688,63.47259682927852,293.0824330786623,331.1476239661798,.8740296840399557,2.912677920919495
1915,Quetzalcoatl,2459600.5,2.543790754476287,.5706410666538692,20.40472660837776,162.9348721741076,347.8091351438147,41.39145147165023,1.092199284997688,3.995382223954886
1916,Boreas,2459600.5,2.272324177667199,.4498393843780145,12.88297395642586,340.5981620510102,335.9167764123868,352.2401366045371,1.250143268478108,3.294505086856289
1917,Cuyo,2459600.5,2.14981121226236,.5054666607865446,23.95922692157032,188.2869783127825,194.5115030151171,82.2843922810623,1.063153317478631,3.236469107046088
1943,Anteros,2459600.5,1.430366783173011,.2560374828122278,8.706034969532251,246.3110706020363,338.3801329232052,173.8814283992249,1.064139272511169,1.796594293834852
1980,Tezcatlipoca,2459600.5,1.709370985747121,.3648359123967504,26.8689695764886,246.560199388918,115.4661353995156,314.1597421163634,1.085731062537538,2.333010908956705
1981,Midas,2459600.5,1.776435963774881,.6501354173857774,39.82986428861084,356.8569898560586,267.8286153975083,202.5329806814936,.621512027006993,2.931359900542769
2059,Baboquivari,2459600.5,2.64324121274608,.531432311471031,11.02055447003622,200.6851159860844,192.4190577597405,181.8930083473287,1.23853742528094,4.04794500021122
2061,Anza,2459600.5,2.264279343476608,.5360981217114927,3.800349706160866,207.3741353983842,157.0286649770264,354.1526556258232,1.050403440408666,3.478155246544549
2062,,2459600.5,.9669087478156669,.1827720931291991,18.9345273941421,108.5428491298942,148.0586126391113,21.46549438015371,.7901848121124645,1.143632683518869
"1979 XB",,2444221.5,2.228085656329666,.7084495059291489,24.73412122397795,86.0555030947377,75.57989828051527,346.3183743701075,.6495994739350907,3.806571838724241
594913,'Aylo'chaxnim,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162

Here is my Fortran program (it contains a main file and some modules):

program Main_NEOs_orbits_TEST

    use DataType
    use Constants
    use DataHandling
 
    implicit none   
    
    ! Declarations
    character*100 :: input_path,output_path_ast_EM_loc, input_filename_ast,input_filename_cmt, output_path, output_filename_ast
    character*118 :: str_line
    character*2   :: str_name
    character*30, dimension (3) :: str_output    
    integer :: i,j,iflag, no_data_lines1,n_lines2, iReturn, num_orb_elem
    type(NEO), dimension (:), allocatable :: Ast_data  
  
    
    ! Definition of constants, paths names and file names
    input_path = 'D:\OneDrive\MSc_Thesis\Projects\NEOs_orbits - TEST\InputFiles\'
    input_filename_ast = 'test_Ast.csv'

        
    ! Reading of asteroids data
    call read_NEOs_data(iu_in1, input_path, input_filename_ast, no_data_lines1, Ast_data)          

    stop

end program Main_NEOs_orbits_TEST
 
**********************************************************************************************************************************************

module Constants

    use DataType

    implicit none

    real(pr), parameter :: ZERO = 0.0_pr, ONE = 1.0_pr, TWO = 2.0_pr, THREE = 3.0_pr, FOUR = 4.0_pr, SEVEN = 7.0_pr 
    real(pr), parameter :: HALF = 0.5_pr, QUART = 0.25_pr
    real(pr), parameter :: DAY = 86400.0_pr, YEAR = 365.25_pr*DAY, CENTURY =  36525.0_pr
    real(pr), parameter :: KILO = 1000.0_pr
    real(pr), parameter :: AU2Km = 149597870.700_pr  ! (from Astronomicals Unit to kilometers)
    
    real(pr), parameter :: tol = 1.e-9_pr
    real(pr), parameter :: xmu = 1.32712440018e11_pr ! (km^3 * s^-2) xmu = G * M_Sun https://ssd.jpl.nasa.gov/astro_par.html
    
    ! Unit number for files
    integer :: iu_in1 = 10   !input file
    integer :: iu_in2 = 11   !input file
    integer :: iu_out1 = 12  !output file
    integer :: iu_out2 = 13  !output file
    
end module Constants

**********************************************************************************************************************************************
module DataHandling
    
    use DataType
    
    implicit none
    
    contains 

    !***********************************************************************
    subroutine read_NEOs_data(UnitNum, FilePath, FileName, DataLinesNum, NEOs_data)
    !***********************************************************************
    ! Subroutine for reading of asteroids database 
    !***********************************************************************
    !  INPUT:

    !
    !  OUTPUT:

    !***********************************************************************
        implicit none
    
        ! Arguments
        integer, intent (in) :: UnitNum
        character (len=*), intent (in) :: FilePath
        character (len=*), intent (in) :: FileName
        integer, intent (out) :: DataLinesNum
        type(NEO), dimension (:), allocatable, intent(out) :: NEOs_data
      
        !Local variables
        integer :: i, iflag
        
        
        open(unit = UnitNum, file = trim(FilePath) // trim(FileName), status='old', & 
                access = 'sequential',form = 'formatted', action='read')
    
            ! Count lines 
            DataLinesNum = 0
            read(UnitNum,*)  ! Header line
            do     
                read(UnitNum,*,iostat = iflag)
                if (iflag/=0) exit
                DataLinesNum =  DataLinesNum + 1
            enddo
         
            rewind(UnitNum)
    
            ! Variables allocation
            allocate(NEOs_data(DataLinesNum))
        
            ! Data reading 
            read(UnitNum,*)   ! skip header line (variables names will be assigned again)
            do i = 1, DataLinesNum
                read(UnitNum,*) NEOs_data(i)         
            enddo
        
        close(unit = UnitNum, status='keep') 
        
        return

    end subroutine read_NEOs_data
    !***********************************************************************
 
end module DataHandling   

**********************************************************************************************************************************************
module DataType

    implicit none

    integer, parameter :: pr = selected_real_kind (p = 15)  ! original value (p = 14) 
    
    !"NEO" data type declaration 
    type  NEO                       !  NEOs data :
        character*20 :: pdes        !  pdes      Object primary designation
        character*20 :: name        !  IAU name  Object IAU name
        real(pr) :: epoch           !  Epoch     Epoch Julian Date (TDB)
        real(pr) :: a               !  a         Semi-major axis (au)
        real(pr) :: e               !  e         Eccentricity       
        real(pr) :: i               !  i         Inclination w.r.t. xy-plane (deg)
        real(pr) :: om              !  om        Longitude of Ascending Node (deg)
        real(pr) :: w               !  w         Argument of Perihelion wrt to ecliptic/equinox (deg)
        real(pr) :: ma              !  ma        Mean anomaly (deg)
        real(pr) :: q               !  q         Perihelion distance (au)
        real(pr) :: ad              !  ad        Aphelion distance (au)
    end type NEO                    
    
end module DataType

I need to mantain the format of the .csv file, so I cannot modify it.
Can you explain me why the line:
594913,'Aylo'i ,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162 produces the above said error?

Error output:

forrtl: severe (59): list-directed I/O syntax error, unit 10, file D:\OneDrive\MSc_Thesis\Projects\NEOs_orbits - TEST\InputFiles\test_Ast.csv
Image              PC                Routine            Line        Source
libifcoremdd.dll   00007FFE5DBBAA5D  Unknown               Unknown  Unknown
libifcoremdd.dll   00007FFE5DC1B6FC  Unknown               Unknown  Unknown
NEOs_orbits_TEST.  00007FF75BB41B9B  DATAHANDLING_mp_R          53  DataHandling.f90
NEOs_orbits_TEST.  00007FF75BB43072  MAIN__                     57  Main_NEOs_orbits_TEST.f90
NEOs_orbits_TEST.  00007FF75BB4332E  Unknown               Unknown  Unknown
NEOs_orbits_TEST.  00007FF75BB45F69  Unknown               Unknown  Unknown
NEOs_orbits_TEST.  00007FF75BB45E8E  Unknown               Unknown  Unknown
NEOs_orbits_TEST.  00007FF75BB45D4E  Unknown               Unknown  Unknown
NEOs_orbits_TEST.  00007FF75BB45FDE  Unknown               Unknown  Unknown
KERNEL32.DLL       00007FFF269C7034  Unknown               Unknown  Unknown
ntdll.dll          00007FFF288A2651  Unknown               Unknown  Unknown

line 53: read(UnitNum,*) NEOs_data(i)
line 57: call read_NEOs_data(iu_in1, input_path, input_filename_ast, no_data_lines1, Ast_data)

Problematic line: 594913,'Aylo'chaxnim,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

画尸师 2025-01-22 04:48:23

Vladimir 解释了为什么不能使用列表定向输入来实现此目的,因为不幸的是使用了引号。这是我如何解决这个问题的一个简单版本,如果我做得正确的话,我会更仔细地将东西打包在模块中:

ijb@LAPTOP-GUG8KQ9I:~/work/stack$ cat csv.f90
Module split_string_module

  Type, Public :: split_string_token
     Character( Len = : ), Allocatable, Public :: token
  End type split_string_token

  Public :: split_string
  
  Private

Contains

  Pure Subroutine split_string( separators, string, tokens )

    ! Split a string given the separators into an array of tokens
    
    Implicit None

    Character( Len = * )                                   , Intent( In    ) :: separators
    Character( Len = * )                                   , Intent( In    ) :: string
    Type( split_string_token ), Dimension( : ), Allocatable, Intent(   Out ) :: tokens

    Type( split_string_token ) :: new_token
    
    Character( Len = : ), Allocatable :: current

    Integer :: split_point
    
    Allocate( tokens( 1:0 ) )

    current = string
    ! While we have some characters
    Do While( Len( current ) > 0 )
       ! Find the first separator
       split_point = Scan( current, separators )
       If( split_point /= 0 ) Then

          ! We have a separator - split the string at that point
          new_token%token = current( 1:split_point - 1 )
          ! Catch the case of the last character in the string being a separator
          If( split_point + 1 <= Len( current ) ) Then
             current = current( split_point + 1: )
          Else
             current = ''
          End If

       Else

          ! No separator found, so the remainder of the string is a token
          new_token%token = current
          current = ''

       End If

       ! Add the token to the list
       tokens = [ tokens, new_token ]

    End Do
    
  End Subroutine split_string
  
End Module split_string_module

Module read_csv_module

  Public :: read_csv_line
  
  Private
  
Contains

  Subroutine read_csv_line( unit, tokens, error )

    ! Read a line and split it into an array of comma separated tokens
    
    Use split_string_module, Only : split_string_token, split_string
    
    Implicit None

    Integer                                                , Intent( In    ) :: unit
    Type( split_string_token ), Dimension( : ), Allocatable, Intent(   Out ) :: tokens
    Integer                                                , Intent(   Out ) :: error

    Integer, Parameter :: max_line_length = 4096
    
    Character( Len = max_line_length ) :: line

    Read( unit, '( a )', iostat = error ) line
    If( error == 0 ) Then
       Call split_string( ',', Trim( line ), tokens )
    End If

  End Subroutine read_csv_line

End Module read_csv_module

Program testit

  Use read_csv_module    , Only : read_csv_line
  Use split_string_module, Only : split_string_token

  Type( split_string_token ), Dimension( : ), Allocatable :: tokens

  Integer :: unit
  Integer :: error
  Integer :: i
  
  Open( newunit = unit, file = 'input.dat' )

  error = 0
  Do While( error == 0 )
     Call read_csv_line( unit, tokens, error )
     If( error == 0 ) Then
        Do i = 1, Size( tokens )
           Write( *, '( a, 3x )', Advance = 'No' ) Trim( tokens( i )%token )
        End Do
        Write( *, * )
     End If
  End Do

  Close( unit )
  
End Program testit
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ gfortran-10 --version
GNU Fortran (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ijb@LAPTOP-GUG8KQ9I:~/work/stack$ gfortran-10 -Wall -Wextra -Wuse-without-only -Werror -fcheck=all -std=f2008 -g -O  csv.f90 
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ cat input.dat 
"pdes","name","epoch","a","e","i","om","w","ma","q","ad"
1580,Betulia,2459600.5,2.197288160959855,.4871550690589618,52.07925829047207,62.2921305585828,159.5134530240992,16.62891169416756,1.126868095165017,3.267708226754692
1620,Geographos,2459600.5,1.245689288381319,.3353623816094239,13.33753650294321,337.1849253204765,276.9463790166408,300.4925456829043,.8279319618844114,1.663446614878227
1627,Ivar,2459600.5,1.86327342970777,.3967369932313492,8.451956512766827,133.120308337423,167.8035837640704,129.0289785125129,1.124043931637646,2.602502927777894
1685,Toro,2459600.5,1.367465568905196,.435966790549019,9.382739662870495,274.2362441040706,127.2114688956593,300.0617970060148,.7712959936433091,1.963635144167082
1862,Apollo,2459600.5,1.470502475713431,.5600430467767759,6.353083928279622,35.56898244993719,286.0386669340027,60.20237527657879,.6469577889220891,2.294047162504772
1863,Antinous,2459600.5,2.25922922966352,.6059920366929147,18.39886422664638,346.4237098245764,268.0896471241496,244.0101430178307,.8901543074235589,3.628304151903481
1864,Daedalus,2459600.5,1.460979692497998,.6144866009907846,22.21536437289675,6.613194571694206,325.6563726287792,196.1166696228387,.5632272471383416,2.358732137857654
1865,Cerberus,2459600.5,1.079986459127503,.4669721847798676,16.09858904525619,212.8963846822369,325.2653260753237,170.2073771841984,.57566282277606,1.584310095478947
1866,Sisyphus,2459600.5,1.893353802479725,.5383695942642949,41.20637430558688,63.47259682927852,293.0824330786623,331.1476239661798,.8740296840399557,2.912677920919495
1915,Quetzalcoatl,2459600.5,2.543790754476287,.5706410666538692,20.40472660837776,162.9348721741076,347.8091351438147,41.39145147165023,1.092199284997688,3.995382223954886
1916,Boreas,2459600.5,2.272324177667199,.4498393843780145,12.88297395642586,340.5981620510102,335.9167764123868,352.2401366045371,1.250143268478108,3.294505086856289
1917,Cuyo,2459600.5,2.14981121226236,.5054666607865446,23.95922692157032,188.2869783127825,194.5115030151171,82.2843922810623,1.063153317478631,3.236469107046088
1943,Anteros,2459600.5,1.430366783173011,.2560374828122278,8.706034969532251,246.3110706020363,338.3801329232052,173.8814283992249,1.064139272511169,1.796594293834852
1980,Tezcatlipoca,2459600.5,1.709370985747121,.3648359123967504,26.8689695764886,246.560199388918,115.4661353995156,314.1597421163634,1.085731062537538,2.333010908956705
1981,Midas,2459600.5,1.776435963774881,.6501354173857774,39.82986428861084,356.8569898560586,267.8286153975083,202.5329806814936,.621512027006993,2.931359900542769
2059,Baboquivari,2459600.5,2.64324121274608,.531432311471031,11.02055447003622,200.6851159860844,192.4190577597405,181.8930083473287,1.23853742528094,4.04794500021122
2061,Anza,2459600.5,2.264279343476608,.5360981217114927,3.800349706160866,207.3741353983842,157.0286649770264,354.1526556258232,1.050403440408666,3.478155246544549
2062,,2459600.5,.9669087478156669,.1827720931291991,18.9345273941421,108.5428491298942,148.0586126391113,21.46549438015371,.7901848121124645,1.143632683518869
"1979 XB",,2444221.5,2.228085656329666,.7084495059291489,24.73412122397795,86.0555030947377,75.57989828051527,346.3183743701075,.6495994739350907,3.806571838724241
594913,'Aylo'chaxnim,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ ./a.out
"pdes"   "name"   "epoch"   "a"   "e"   "i"   "om"   "w"   "ma"   "q"   "ad"   
1580   Betulia   2459600.5   2.197288160959855   .4871550690589618   52.07925829047207   62.2921305585828   159.5134530240992   16.62891169416756   1.126868095165017   3.267708226754692   
1620   Geographos   2459600.5   1.245689288381319   .3353623816094239   13.33753650294321   337.1849253204765   276.9463790166408   300.4925456829043   .8279319618844114   1.663446614878227   
1627   Ivar   2459600.5   1.86327342970777   .3967369932313492   8.451956512766827   133.120308337423   167.8035837640704   129.0289785125129   1.124043931637646   2.602502927777894   
1685   Toro   2459600.5   1.367465568905196   .435966790549019   9.382739662870495   274.2362441040706   127.2114688956593   300.0617970060148   .7712959936433091   1.963635144167082   
1862   Apollo   2459600.5   1.470502475713431   .5600430467767759   6.353083928279622   35.56898244993719   286.0386669340027   60.20237527657879   .6469577889220891   2.294047162504772   
1863   Antinous   2459600.5   2.25922922966352   .6059920366929147   18.39886422664638   346.4237098245764   268.0896471241496   244.0101430178307   .8901543074235589   3.628304151903481   
1864   Daedalus   2459600.5   1.460979692497998   .6144866009907846   22.21536437289675   6.613194571694206   325.6563726287792   196.1166696228387   .5632272471383416   2.358732137857654   
1865   Cerberus   2459600.5   1.079986459127503   .4669721847798676   16.09858904525619   212.8963846822369   325.2653260753237   170.2073771841984   .57566282277606   1.584310095478947   
1866   Sisyphus   2459600.5   1.893353802479725   .5383695942642949   41.20637430558688   63.47259682927852   293.0824330786623   331.1476239661798   .8740296840399557   2.912677920919495   
1915   Quetzalcoatl   2459600.5   2.543790754476287   .5706410666538692   20.40472660837776   162.9348721741076   347.8091351438147   41.39145147165023   1.092199284997688   3.995382223954886   
1916   Boreas   2459600.5   2.272324177667199   .4498393843780145   12.88297395642586   340.5981620510102   335.9167764123868   352.2401366045371   1.250143268478108   3.294505086856289   
1917   Cuyo   2459600.5   2.14981121226236   .5054666607865446   23.95922692157032   188.2869783127825   194.5115030151171   82.2843922810623   1.063153317478631   3.236469107046088   
1943   Anteros   2459600.5   1.430366783173011   .2560374828122278   8.706034969532251   246.3110706020363   338.3801329232052   173.8814283992249   1.064139272511169   1.796594293834852   
1980   Tezcatlipoca   2459600.5   1.709370985747121   .3648359123967504   26.8689695764886   246.560199388918   115.4661353995156   314.1597421163634   1.085731062537538   2.333010908956705   
1981   Midas   2459600.5   1.776435963774881   .6501354173857774   39.82986428861084   356.8569898560586   267.8286153975083   202.5329806814936   .621512027006993   2.931359900542769   
2059   Baboquivari   2459600.5   2.64324121274608   .531432311471031   11.02055447003622   200.6851159860844   192.4190577597405   181.8930083473287   1.23853742528094   4.04794500021122   
2061   Anza   2459600.5   2.264279343476608   .5360981217114927   3.800349706160866   207.3741353983842   157.0286649770264   354.1526556258232   1.050403440408666   3.478155246544549   
2062      2459600.5   .9669087478156669   .1827720931291991   18.9345273941421   108.5428491298942   148.0586126391113   21.46549438015371   .7901848121124645   1.143632683518869   
"1979 XB"      2444221.5   2.228085656329666   .7084495059291489   24.73412122397795   86.0555030947377   75.57989828051527   346.3183743701075   .6495994739350907   3.806571838724241   
594913   'Aylo'chaxnim   2459600.5   .5554326489245599   .1770230892406738   15.86839958719851   6.704982245275168   187.3289626591178   211.0111749229703   .4571082455468037   .6537570523023162   
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ 

Vladimir explains why you can not use list directed input for this, due to the unfortunate use of inverted commas. Here is a simple version of how I might go about addressing this problem, were I doing it properly I would package things up in modules a bit more carefully:

ijb@LAPTOP-GUG8KQ9I:~/work/stack$ cat csv.f90
Module split_string_module

  Type, Public :: split_string_token
     Character( Len = : ), Allocatable, Public :: token
  End type split_string_token

  Public :: split_string
  
  Private

Contains

  Pure Subroutine split_string( separators, string, tokens )

    ! Split a string given the separators into an array of tokens
    
    Implicit None

    Character( Len = * )                                   , Intent( In    ) :: separators
    Character( Len = * )                                   , Intent( In    ) :: string
    Type( split_string_token ), Dimension( : ), Allocatable, Intent(   Out ) :: tokens

    Type( split_string_token ) :: new_token
    
    Character( Len = : ), Allocatable :: current

    Integer :: split_point
    
    Allocate( tokens( 1:0 ) )

    current = string
    ! While we have some characters
    Do While( Len( current ) > 0 )
       ! Find the first separator
       split_point = Scan( current, separators )
       If( split_point /= 0 ) Then

          ! We have a separator - split the string at that point
          new_token%token = current( 1:split_point - 1 )
          ! Catch the case of the last character in the string being a separator
          If( split_point + 1 <= Len( current ) ) Then
             current = current( split_point + 1: )
          Else
             current = ''
          End If

       Else

          ! No separator found, so the remainder of the string is a token
          new_token%token = current
          current = ''

       End If

       ! Add the token to the list
       tokens = [ tokens, new_token ]

    End Do
    
  End Subroutine split_string
  
End Module split_string_module

Module read_csv_module

  Public :: read_csv_line
  
  Private
  
Contains

  Subroutine read_csv_line( unit, tokens, error )

    ! Read a line and split it into an array of comma separated tokens
    
    Use split_string_module, Only : split_string_token, split_string
    
    Implicit None

    Integer                                                , Intent( In    ) :: unit
    Type( split_string_token ), Dimension( : ), Allocatable, Intent(   Out ) :: tokens
    Integer                                                , Intent(   Out ) :: error

    Integer, Parameter :: max_line_length = 4096
    
    Character( Len = max_line_length ) :: line

    Read( unit, '( a )', iostat = error ) line
    If( error == 0 ) Then
       Call split_string( ',', Trim( line ), tokens )
    End If

  End Subroutine read_csv_line

End Module read_csv_module

Program testit

  Use read_csv_module    , Only : read_csv_line
  Use split_string_module, Only : split_string_token

  Type( split_string_token ), Dimension( : ), Allocatable :: tokens

  Integer :: unit
  Integer :: error
  Integer :: i
  
  Open( newunit = unit, file = 'input.dat' )

  error = 0
  Do While( error == 0 )
     Call read_csv_line( unit, tokens, error )
     If( error == 0 ) Then
        Do i = 1, Size( tokens )
           Write( *, '( a, 3x )', Advance = 'No' ) Trim( tokens( i )%token )
        End Do
        Write( *, * )
     End If
  End Do

  Close( unit )
  
End Program testit
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ gfortran-10 --version
GNU Fortran (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ijb@LAPTOP-GUG8KQ9I:~/work/stack$ gfortran-10 -Wall -Wextra -Wuse-without-only -Werror -fcheck=all -std=f2008 -g -O  csv.f90 
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ cat input.dat 
"pdes","name","epoch","a","e","i","om","w","ma","q","ad"
1580,Betulia,2459600.5,2.197288160959855,.4871550690589618,52.07925829047207,62.2921305585828,159.5134530240992,16.62891169416756,1.126868095165017,3.267708226754692
1620,Geographos,2459600.5,1.245689288381319,.3353623816094239,13.33753650294321,337.1849253204765,276.9463790166408,300.4925456829043,.8279319618844114,1.663446614878227
1627,Ivar,2459600.5,1.86327342970777,.3967369932313492,8.451956512766827,133.120308337423,167.8035837640704,129.0289785125129,1.124043931637646,2.602502927777894
1685,Toro,2459600.5,1.367465568905196,.435966790549019,9.382739662870495,274.2362441040706,127.2114688956593,300.0617970060148,.7712959936433091,1.963635144167082
1862,Apollo,2459600.5,1.470502475713431,.5600430467767759,6.353083928279622,35.56898244993719,286.0386669340027,60.20237527657879,.6469577889220891,2.294047162504772
1863,Antinous,2459600.5,2.25922922966352,.6059920366929147,18.39886422664638,346.4237098245764,268.0896471241496,244.0101430178307,.8901543074235589,3.628304151903481
1864,Daedalus,2459600.5,1.460979692497998,.6144866009907846,22.21536437289675,6.613194571694206,325.6563726287792,196.1166696228387,.5632272471383416,2.358732137857654
1865,Cerberus,2459600.5,1.079986459127503,.4669721847798676,16.09858904525619,212.8963846822369,325.2653260753237,170.2073771841984,.57566282277606,1.584310095478947
1866,Sisyphus,2459600.5,1.893353802479725,.5383695942642949,41.20637430558688,63.47259682927852,293.0824330786623,331.1476239661798,.8740296840399557,2.912677920919495
1915,Quetzalcoatl,2459600.5,2.543790754476287,.5706410666538692,20.40472660837776,162.9348721741076,347.8091351438147,41.39145147165023,1.092199284997688,3.995382223954886
1916,Boreas,2459600.5,2.272324177667199,.4498393843780145,12.88297395642586,340.5981620510102,335.9167764123868,352.2401366045371,1.250143268478108,3.294505086856289
1917,Cuyo,2459600.5,2.14981121226236,.5054666607865446,23.95922692157032,188.2869783127825,194.5115030151171,82.2843922810623,1.063153317478631,3.236469107046088
1943,Anteros,2459600.5,1.430366783173011,.2560374828122278,8.706034969532251,246.3110706020363,338.3801329232052,173.8814283992249,1.064139272511169,1.796594293834852
1980,Tezcatlipoca,2459600.5,1.709370985747121,.3648359123967504,26.8689695764886,246.560199388918,115.4661353995156,314.1597421163634,1.085731062537538,2.333010908956705
1981,Midas,2459600.5,1.776435963774881,.6501354173857774,39.82986428861084,356.8569898560586,267.8286153975083,202.5329806814936,.621512027006993,2.931359900542769
2059,Baboquivari,2459600.5,2.64324121274608,.531432311471031,11.02055447003622,200.6851159860844,192.4190577597405,181.8930083473287,1.23853742528094,4.04794500021122
2061,Anza,2459600.5,2.264279343476608,.5360981217114927,3.800349706160866,207.3741353983842,157.0286649770264,354.1526556258232,1.050403440408666,3.478155246544549
2062,,2459600.5,.9669087478156669,.1827720931291991,18.9345273941421,108.5428491298942,148.0586126391113,21.46549438015371,.7901848121124645,1.143632683518869
"1979 XB",,2444221.5,2.228085656329666,.7084495059291489,24.73412122397795,86.0555030947377,75.57989828051527,346.3183743701075,.6495994739350907,3.806571838724241
594913,'Aylo'chaxnim,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ ./a.out
"pdes"   "name"   "epoch"   "a"   "e"   "i"   "om"   "w"   "ma"   "q"   "ad"   
1580   Betulia   2459600.5   2.197288160959855   .4871550690589618   52.07925829047207   62.2921305585828   159.5134530240992   16.62891169416756   1.126868095165017   3.267708226754692   
1620   Geographos   2459600.5   1.245689288381319   .3353623816094239   13.33753650294321   337.1849253204765   276.9463790166408   300.4925456829043   .8279319618844114   1.663446614878227   
1627   Ivar   2459600.5   1.86327342970777   .3967369932313492   8.451956512766827   133.120308337423   167.8035837640704   129.0289785125129   1.124043931637646   2.602502927777894   
1685   Toro   2459600.5   1.367465568905196   .435966790549019   9.382739662870495   274.2362441040706   127.2114688956593   300.0617970060148   .7712959936433091   1.963635144167082   
1862   Apollo   2459600.5   1.470502475713431   .5600430467767759   6.353083928279622   35.56898244993719   286.0386669340027   60.20237527657879   .6469577889220891   2.294047162504772   
1863   Antinous   2459600.5   2.25922922966352   .6059920366929147   18.39886422664638   346.4237098245764   268.0896471241496   244.0101430178307   .8901543074235589   3.628304151903481   
1864   Daedalus   2459600.5   1.460979692497998   .6144866009907846   22.21536437289675   6.613194571694206   325.6563726287792   196.1166696228387   .5632272471383416   2.358732137857654   
1865   Cerberus   2459600.5   1.079986459127503   .4669721847798676   16.09858904525619   212.8963846822369   325.2653260753237   170.2073771841984   .57566282277606   1.584310095478947   
1866   Sisyphus   2459600.5   1.893353802479725   .5383695942642949   41.20637430558688   63.47259682927852   293.0824330786623   331.1476239661798   .8740296840399557   2.912677920919495   
1915   Quetzalcoatl   2459600.5   2.543790754476287   .5706410666538692   20.40472660837776   162.9348721741076   347.8091351438147   41.39145147165023   1.092199284997688   3.995382223954886   
1916   Boreas   2459600.5   2.272324177667199   .4498393843780145   12.88297395642586   340.5981620510102   335.9167764123868   352.2401366045371   1.250143268478108   3.294505086856289   
1917   Cuyo   2459600.5   2.14981121226236   .5054666607865446   23.95922692157032   188.2869783127825   194.5115030151171   82.2843922810623   1.063153317478631   3.236469107046088   
1943   Anteros   2459600.5   1.430366783173011   .2560374828122278   8.706034969532251   246.3110706020363   338.3801329232052   173.8814283992249   1.064139272511169   1.796594293834852   
1980   Tezcatlipoca   2459600.5   1.709370985747121   .3648359123967504   26.8689695764886   246.560199388918   115.4661353995156   314.1597421163634   1.085731062537538   2.333010908956705   
1981   Midas   2459600.5   1.776435963774881   .6501354173857774   39.82986428861084   356.8569898560586   267.8286153975083   202.5329806814936   .621512027006993   2.931359900542769   
2059   Baboquivari   2459600.5   2.64324121274608   .531432311471031   11.02055447003622   200.6851159860844   192.4190577597405   181.8930083473287   1.23853742528094   4.04794500021122   
2061   Anza   2459600.5   2.264279343476608   .5360981217114927   3.800349706160866   207.3741353983842   157.0286649770264   354.1526556258232   1.050403440408666   3.478155246544549   
2062      2459600.5   .9669087478156669   .1827720931291991   18.9345273941421   108.5428491298942   148.0586126391113   21.46549438015371   .7901848121124645   1.143632683518869   
"1979 XB"      2444221.5   2.228085656329666   .7084495059291489   24.73412122397795   86.0555030947377   75.57989828051527   346.3183743701075   .6495994739350907   3.806571838724241   
594913   'Aylo'chaxnim   2459600.5   .5554326489245599   .1770230892406738   15.86839958719851   6.704982245275168   187.3289626591178   211.0111749229703   .4571082455468037   .6537570523023162   
ijb@LAPTOP-GUG8KQ9I:~/work/stack$ 
撑一把青伞 2025-01-22 04:48:23

列表定向格式非常方便,但同时也相当复杂。

在这种情况下,您正在阅读以撇号开头的内容,包含另一个撇号,因此看起来像撇号分隔的序列。在撇号分隔的字符序列中,撇号是分隔符,不被视为字符串的一部分。但是,此 'Aylo'chaxnim 无效,因为它在分隔撇号之后还有另一个杂散字符。如果您需要解析它,您将需要一些自定义解析器,而不是通用的列表定向格式。

另一种选择是认为此 'Aylo'chaxnim 无效(可能是数据提供者错误输入的)并在将其提供给您的程序之前将其删除。要么手动(如果仅作为异常发生),要么通过某些预处理脚本。

请注意,如果起始撇号之前有其他字符,也没有问题。在这种情况下,内部撇号不会被解释为分隔符,而是被解释为字符串中的普通字符。


正如伊恩·布什所示,这个名字是一个合法的小行星名称。因此,如果您需要读取正确的名称 'Aylo'chaxnim,您将需要自己解析该行。您可以通过本地化逗号来对其进行标记,然后解析各个标记。

还有可用的 CSV 阅读器库,但您必须检查它们是否确实能够应对此问题。

The list directed format is quite convenient, but at the same time quite complicated.

In this case you are reading something that starts with an apostrophe, contains another apostrophe and hence looks like an apostrophe-delimited sequence. In apostrophe-delimited character sequences the apostrophes are delimiters and are not considered to be a part of the string. However, this 'Aylo'chaxnim is then invalid because it has another stray characters after the delimiting apostrophe. If you need to parse this, you will need some custom parser and not the generic list-directed format.

Another option is consider this 'Aylo'chaxnim to be invalid (probably entered by the data provider by mistake) and remove it before giving it to your program. either manually, if it happens only as an exception, or by some pre-processing script.

Note that if there are additional characters before the starting apostrophe, it is fine. In that case the internal apostrophes are not interpreted as delimiters, but as normal characters in the character string.


As Ian Bush shown, the name is a legitimate asteroid name. So if you need to read the correct name 'Aylo'chaxnim you will need to parse the line yourself. You can tokenize it by localizing the commas and then parse the individual tokens.

There are also CSV reader libraries available but you have to check that they are actually able to cope with this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文