I have a .dat file , from which I am trying to read line by line and print it. Can anyone please help about how to do it in fortran?
Thanks in advance!
Data:
REMARK GENERATED BY TRJCONV
TITLE UNNAMED t= 0.00000
REMARK THIS IS A SIMULATION BOX
CRYST1 26.178 26.178 26.178 90.00 90.00 90.00 P 1 1
MODEL 1
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
TER
ENDMDL
Code:
program atom_test
implicit none
character (LEN=75) ::inputdatafile,outputfile
real,dimension(100) :: x, y
integer :: i,n,nframes
character (len=200),dimension(3000):: command
print *,"Give the datafile name:"
read *,inputdatafile
outputfile=inputdatafile(1:len(trim(inputdatafile))-4)//"_output.dat"
!write(*,*)outputfile
Open(9, file=inputdatafile, status='old')
call linesFile(inputdatafile,n)
write(*,*)n
do i=1,n
read(*,*),command(i)
write (*,*)command(i)
end do
close(9)
end program atom_test
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! find the number of lines in a file
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine linesFile(fileIn,n)
implicit none
Character(len = 50) :: fileIn
integer, intent(out) :: n
! locals
integer :: iostatus, unit_read
real :: dummy
unit_read = 9
open(unit=unit_read, file=fileIn)
n =0
DO
READ(unit_read, *, IOSTAT=iostatus) dummy
IF (iostatus < 0) EXIT
n = n + 1
END DO
! WRITE(*, '(i8, a, a)') n, ' bins read from file: ', fileIn
close(unit_read)
end subroutine linesFile
Given marked answer works fine. As I am very new in Fortran I have one more question related this. I want to get the elements separately from the ATOM rows in my data file for example: ATOM 1 S2 LJ2 1 17.000 15.030 11.630 1.00 0.00
from here i want to store 1,s2,LJ2,1,17.000,15.030 each in different parameters. In that case I am using this
/* With the code marked as correct
ncount=0
do i = 1, n
IF (command(i)(1:4).eq.'ATOM') THEN
ncount=ncount+1
read(read_unit,*) p, p2, p3,p4,xatom(ncount)
write(*,*),p
endif
end do
But it is not working.Can you please give me one suggestion about how to read individually from those lines which starts with ATOM? Thanks in advance!
There are a few things I notice straight away:
read(*, *) command(i)
reads the first element of standard input, not from the file. I think you want to read(9, *)
.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 to IOSTAT
being non-zero, even if you haven't reached the end of the file. Always read a character
variable.