Reading data file in Fortran with known number of lines but unknown number of entries in each line

前端 未结 5 935
孤街浪徒
孤街浪徒 2020-12-02 01:24

How can I read the data file containing known number of lines but the number of entries in each line is unknown, e.g. if my data file contain some thing like

相关标签:
5条回答
  • 2020-12-02 01:41

    An implementation based on what M. S. B. pointed out. Quite late, but I guess it could be useful to someone.

    Have an array of the type you expect to read ready:

    double precision, dimension(MAX_NUM_OF_COLS) :: test_array
    

    Read a line from your file:

    READ(reading_unit,'(A)',iostat=io) line
    

    Loop and try to read from the line a maximum quantity of numbers:

    do i=1,MAX_NUM_OF_COLS
      READ(line, *, iostat=io) test_array(1:i)
      if(io==0) exit
    enddo
    
    write(*,*) 'number of columns = ', (i-1)
    

    If needed, loop this over all the lines of your file, and keep the maximum or minimum number of columns.

    Minimum example:

    integer, parameter :: MAX_NUM_OF_COLS=30
    integer, parameter :: MAX_LINE_LENGTH=1000
    character(len=MAX_LINE_LENGTH) line
    integer i, io, reading_unit
    double precision, dimension(MAX_NUM_OF_COLS) :: test_array
    
    reading_unit=100
    OPEN(reading_unit, file='the_file')
    
    ! Get first line of file.
    DO
      READ(reading_unit,'(A)',iostat=io) line
      IF (io/=0) then
        write(*,*) "Error reading file."
        stop
      endif
      exit ! Eventually, do not exit and put the DO loop below here.
    ENDDO
    CLOSE(reading_unit)
    
    do i=1,MAX_NUM_OF_COLS
      READ(line,*,iostat=io) test_array(1:i)
      if(io==-1) exit
    enddo
    
    write(*,*) 'number of columns = ', (i-1)
    
    0 讨论(0)
  • 2020-12-02 01:42

    One method: read the line into a string, using a string that is at least as long as the longest expected line. Then you go about parsing the string. E.g., if the numbers are always split by spaces, use that to figure out the substring boundaries. Then you can use "internal reads" to read from each sub-string to obtain the numeric values. An internal read uses a string instead of a unit number and obtains the data from the string -- at least you don't have to recreate the conversion of characters to numeric values, the read statement will do that for you. The intrinsic functions provided with Fortran will make the parsing easier.

    0 讨论(0)
  • 2020-12-02 01:42
    integer,parameter :: reclen=99999        ! maximum record length
    integer,parameter :: undef=-9999         ! undefined value
    integer :: actual_reclen                 ! actual record length
    integer,dimension(reclen) :: dummy=undef ! dummy array used for reading
    integer,dimension(:),allocatable :: a    ! final array
    
    open(unit=10,file='sample.txt',form='formatted',access='sequential')
    read(unit=10,fmt=*,end=101)(dummy(i),i=1,reclen)
    101 close(unit=10)
    
    actual_reclen=COUNT(dummy/=undef)
    allocate(a(actual_reclen))
    a=dummy(1:actual_reclen)
    
    end
    
    0 讨论(0)
  • 2020-12-02 01:46

    This is a program that can count numbers in a line (or number of columns) but for a line. If you have many lines, you should change it slightly.

    program test12
    
    implicit none
    
    integer n,m,i
    
    integer,allocatable::x(:)
    
     open(10,file='C:\Users\user\Desktop\file.txt')
    
    allocate(x(n))
    
    20 n=n+1
    
     deallocate(x) 
    
    
    
     allocate(x(n))
    
    read(10,*,iostat=m)(x(i),i=1,n)
    
    if (m==-1)then
    
    goto 30
    
    else
    
    
    rewind 10
    
     goto 20
    
    end if
    
     30 print*,n-1
    
     end
    
    0 讨论(0)
  • 2020-12-02 01:51

    Assuming that you're okay with padding the array with zeros (specifically referring to the later duplicate question here), this is my idea:

    Read the data line by line into a string, then append a number of zeros, finally read each row of the data from this array. Here's an example:

    program unknown_numbers
    
        implicit none
        integer, parameter :: nrow=3, ncol=14
        integer :: data(ncol, nrow)
        character(len=2*ncol) :: zeros ! will contain lots of zeros
        character(len=10*ncol) :: line ! temporary storage for each line of the file
        integer :: i, u
    
        ! Write " 0 0 0 0 0 0 0 0" into the string "zeros"
        write(zeros, '(*(I2))') [(0, i=1, ncol)]
    
        open(newunit=u, file='data.txt', status='old', action='read')
    
        do i = 1, nrow, 1
            ! Read the next line into a temporary string array
            read(u, '(A)') line
            ! Append a number of zeros to the temporary string
            line = trim(line) // zeros
            ! Read the row of data from the string.
            read(line, *) data(:, i)
        end do
    
        close(u)
    
        ! For testing purposes, print the data.
        print '(14(X, I3))', data
    
    end program unknown_numbers
    
    0 讨论(0)
提交回复
热议问题