Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Reading a text file without knowing the number of columns of data in Fortran 77.

Status
Not open for further replies.

ARR86

Programmer
Apr 6, 2012
5
DE
Hello All

I want to read a file that can contain different number of columns of data everytime in Fortran 77. i.e. I dont know the number of columns beforehand.If I know the number of columns,I can read the file like this way

SUBROUTINE varread(TNo,X,Y,Z,VARL)

IMPLICIT NONE

INTEGER NMAX
PARAMETER(NMAX=10000)
Integer N(NMAX),i,j,TNo
double precision X(NMAX),Y(NMAX),Z(NMAX),VARL(NMAX)

OPEN(35,file='exp1.txt')
j = 0
DO WHILE(.true.)
j = j+1
READ(35,600,END=900) N(j),X(j),Y(j),Z(j),VARL(j)
600 FORMAT(I4,1x,E16.7,1x,E16.7,1x,E16.7,1x,E11.4)
END DO
900 continue
TNo = j-1
CLOSE(35)

RETURN
END

In this file exp1.txt,I know that i will always have five columns of data namely N,X,Y,Z,VARL.So I read them easily using the format statement.
But in the file i want to read i know that it can have large number of columns but not how many.

I dont want to store the data in say 50 different variables.Is there a way to read the entire file as an array?.

Can somebody help me read the data?.

Regards
Anbazhagan.



 
Hmmm,

what makes you think that you are using Fortran77 ? At least the statement

DO WHILE(.true.)

is not a standard Fortran77 statement. The reason why I ask this is, that with Fortran 90/95 or later there is a chance to solve this problem, in Fortran77 I think not.

But to carry on, you should specify what you know about the file to read.
Do you know which datatypes it contains and their sequence if not uniform ?
Do you know the delimiter that is used to seperate the data ?
Do you know the length of one record of this file ?
Do all records of one given file have the same format as the first ?

The procedure I would propose is something like this

- define an allocatable array of the type you want to read from the file, maybe you a derived datatype is needed
- read one record into a string variable of sufficient length
- check how many delimiters occur in this string to the end of data
- allocate the number of elements in the array to the number of delimiters + 1
- read this array from the string.
- select and save the data that you are interested in from the array.
- continue reading the following records or redefine the number of elements to the array depending if the format changes from line to line or not.

Norbert


The optimist believes we live in the best of all possible worlds - the pessimist fears this might be true.
 
Just last week, I found myself in a similar boat. This is what was good enough for my application as far as finding out how many columns of data a particular line had...a function that returns the number of items in a line.
Code:
! number of space-separated items in a line
integer function nitems(line)
    character line*(*)    
    logical back
    integer length
    
    back = .true.        
    length = len_trim(line)    
    k = index(line(1:length), ' ', back)
    if (k == 0) then
        nitems = 0
        return
    end if    
    
    nitems = 1
    do 
        ! starting with the right most blank space, 
        ! look for the next non-space character down
        ! indicating there is another item in the line
        do
            if (k <= 0) exit
            
            if (line(k:k) == ' ') then
                k = k - 1
                cycle
            else
                nitems = nitems + 1
                exit
            end if
            
        end do
        
        ! once a non-space character is found,
        ! skip all adjacent non-space character
        do
            if ( k<=0 ) exit
            
            if (line(k:k) /= ' ') then
                k = k - 1
                cycle
            end if
            
            exit
            
        end do
        
        if (k <= 0) exit
            
    end do
end function nitems
It is understood that you are reading the input file one line at a time and that is the string being passed to the function.
 
My 2 cents:
Code:
integer function ntokens(line)
character,intent(in):: line*(*)
integer i, n, toks

i = 1;
n = len_trim(line)
toks = 0
ntokens = 0
do while(i <= n)
   do while(line(i:i) == ' ') 
     i = i + 1
     if (n < i) return
   enddo
   toks = toks + 1
   ntokens = toks
   do
     i = i + 1
     if (n < i) return
     if (line(i:i) == ' ') exit
   enddo
enddo
end function ntokens
 
Hi

Thank you all for the replies. I was busy with my exams that is why i could not thank you earlier.
The file i want to read contains real data with two spaces as delimiter.
Once i find the number of columns in the file,how can i read and store it in a array?. What syntax of the format statement should i use?.Also it would be really helpful if you could tell me how to write the large columns of data to a file?. I don't have much knowledge in FORTRAN.It would be really helpful if you could help me out.

Regards
Anbazhgan.

 
It would be really helpful if you studied a little bit of fortran; otherwise, you are going to need more help on the next step. This thing you are asking is one of the most basic stuff...you should know this much.

 
I think my earlier comment was misunderstood.The thing is i am transferring the code from matlab to fortran. I don't have problem in the logic part which is 90% moved to fortran. I am having problem in reading and writing the data, especially multidimensional array. I dont have any issues in reading and writing single columns of data such as XPOS(1000,1) etc in the post above. If XPOS is XPOS(1000,60),how to write it to a file?.I am using the statements below but it outputs in the wrong way.

No=60
NDIV=1000
OPEN(55,file='wv_num.txt')
DO J=1,No
WRITE(55,485),(XPOS(I,J),I=1,NDIV)
485 FORMAT(60(I4))
ENDDO
CLOSE(55)


And if a file has say 60 columns of data,how one should read it? Is it possible to store them in a single multidimensional array or should i use 60 separate variables in the read statement?

Regards
Anbazahgan.
 
Now you are talking...I can see the problem, too...you have your dimensions 'swapped'...

Your format statement is set to write 60 numbers in a row (horizontally) but you are asking it to write 1000! (NDIV)

I think your code needs to look like this:

No=60
NDIV=1000
OPEN(55,file='wv_num.txt')
DO I=1,NDIV
WRITE(55,485),(XPOS(I,J),J=1,No)
485 FORMAT(60(I4))
ENDDO
CLOSE(55)

Of course, I just assumed that your XPOS matrix is 1000x60.

The point is that the number in the implicit loop and the multiplier in the format statement need to match.

If you matrix is 60x1000, then, clearly you need format(1000(I4))
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top