In fortran how to read all strings line by line from a .dat file in fortran
There are a few things I notice straight away:
- The line
read(*, *) command(i)
reads the first element of standard input, not from the file. I think you want toread(9, *)
. - Actually, you'll probably want to
read(9, '(A)')
because you want to read the whole line, not just until the first element separator (i.e. space or comma). In your subroutine, you open the file again, under the same unit. That is... dangerous if not wrong. Better to just read from the file, then use the
rewind
command to move the read position back to the beginning of the file.program atom_test implicit none integer :: ios integer, parameter :: read_unit = 99 character(len=200), allocatable :: command(:) character(len=200) :: line integer :: n, i open(unit=read_unit, file='data.dat', iostat=ios) if ( ios /= 0 ) stop "Error opening file data.dat" n = 0 do read(read_unit, '(A)', iostat=ios) line if (ios /= 0) exit n = n + 1 end do print*, "File contains ", n, "commands" allocate(command(n)) rewind(read_unit) do i = 1, n read(read_unit, '(A)') command(i) end do close(read_unit) do i = 1, n print*, command(i) end do end program atom_test
If you already dedicate 3000 lines in the beginning, there's no real reason to read everything twice:
program atom_test implicit none integer :: ios integer, parameter :: read_unit = 99 character(len=200) :: command(3000) integer :: n, i open(unit=read_unit, file='data.dat', iostat=ios) if ( ios /= 0 ) stop "Error opening file data.dat" n = 0 do read(read_unit, '(A)', iostat=ios) command(n+1) if (ios /= 0) exit n = n + 1 end do print*, "File contains ", n, "commands" close(read_unit) do i = 1, n print*, command(i) end do end program atom_test
In your subroutine to read the number of lines in the file, you try to read a
REAL
from a file where the first word is often not a number. This might lead toIOSTAT
being non-zero, even if you haven't reached the end of the file. Always read acharacter
variable.
This post provides an answer to OP comment:
I want to get the elements separately from the ATOM rows in my data file
Assuming input.txt
looks like:
ATOM 1 S2 LJ2 1 17.000 15.030 11.630 1.00 0.00
ATOM 2 S2 LJ2 2 13.290 11.340 15.900 1.00 0.00
ATOM 3 S2 LJ2 3 17.030 23.070 14.750 1.00 0.00
ATOM 4 S2 LJ2 4 15.360 14.840 9.480 1.00 0.00
ATOM 5 S2 LJ2 5 15.780 4.560 9.580 1.00 0.00
ATOM 6 S2 LJ2 6 5.350 22.490 11.110 1.00 0.00
ATOM 7 S2 LJ2 7 19.940 3.910 10.840 1.00 0.00
ATOM 8 S2 LJ2 8 20.380 13.360 15.680 1.00 0.00
ATOM 9 S2 LJ2 9 18.340 4.200 7.720 1.00 0.00
ATOM 10 S2 LJ2 10 18.610 16.530 9.910 1.00 0.00
You could
- read columns into strings
- read real numbers from strings
- output the results
program fort
integer n, i
parameter (n=10)
real r1(n), r2(n), r3(n), r4(n), r5(n), r6(n), r7(n)
character(len=255) format, s1(n), s2(n), s3(n), s4(n), s5(n),
& s6(n), s7(n), s8(n), s9(n), s10(n)
i=1
open(unit=99, file='input.txt')
2 read(99,3,end=1) s1(i), s2(i), s3(i), s4(i), s5(i),
& s6(i), s7(i), s8(i), s9(i), s10(i)
i=i+1
goto 2
3 format(a6,2a4,a5,a4,3a8,a6,a4)
4 format(a6,f4.1,2x,2a4,f4.1,5f8.3)
1 close(99)
read(s2,*) r1
read(s5,*) r2
read(s6,*) r3
read(s7,*) r4
read(s8,*) r5
read(s9,*) r6
read(s10,*) r7
do i=1,n
write(*,4) s1(i), r1(i), s3(i), s4(i), r2(i),
& r3(i), r4(i), r5(i), r6(i), r7(i)
enddo
end
output:
ATOM 1.0 S2 LJ2 1.0 17.000 15.030 11.630 1.000 0.000
ATOM 2.0 S2 LJ2 2.0 13.290 11.340 15.900 1.000 0.000
ATOM 3.0 S2 LJ2 3.0 17.030 23.070 14.750 1.000 0.000
ATOM 4.0 S2 LJ2 4.0 15.360 14.840 9.480 1.000 0.000
ATOM 5.0 S2 LJ2 5.0 15.780 4.560 9.580 1.000 0.000
ATOM 6.0 S2 LJ2 6.0 5.350 22.490 11.110 1.000 0.000
ATOM 7.0 S2 LJ2 7.0 19.940 3.910 10.840 1.000 0.000
ATOM 8.0 S2 LJ2 8.0 20.380 13.360 15.680 1.000 0.000
ATOM 9.0 S2 LJ2 9.0 18.340 4.200 7.720 1.000 0.000
ATOM 10.0 S2 LJ2 10.0 18.610 16.530 9.910 1.000 0.000
A better approach consists on
- read columns into variables (strings, integers, or reals)
- output the results
program fort
integer n, i
parameter (n=10)
integer i1(n), i2(n)
real r1(n), r2(n), r3(n), r4(n), r5(n)
character(len=255) format, s1(n), s2(n), s3(n), s4(n), s5(n),
& s6(n), s7(n), s8(n), s9(n), s10(n)
i=1
open(unit=99, file='input.txt')
2 read(99,3,end=1) s1(i), i1(i), s3(i), s4(i), i2(i),
& r1(i), r2(i), r3(i), r4(i), r5(i)
i=i+1
goto 2
3 format(a6,i4,a4,a5,i4,3f8.3,2f6.2)
4 format(a6,i4,2x,2a4,i4,5f8.3)
1 close(99)
do i=1,n
write(*,4) s1(i), i1(i), s3(i), s4(i), i2(i),
& r1(i), r2(i), r3(i), r4(i), r5(i)
enddo
end