Silverfrost Forums

Welcome to our forums

Fixed length binary file (Fortran)

23 Sep 2011 8:35 #9009

Hi,

I'm reading a fixed length binary file which has several records.I know the length of each record.

I would like to know (for some reson) the number of records that exist in the file which I'm reading.Is there any method, wherein I could detect the number of records existing?

That would make some things easy for me.

Please help

Christy

23 Sep 2011 10:32 #9010

May be like this?

call file_size@(file,size,err_code)
if (err_code .eq. 0) number_of_rec = size/length_of_rec

Regards - Wilfried

24 Sep 2011 6:36 #9016

Thanks Wilfred.

Did not get that (sorry)

Do you mean :

call file_size(file,size,err_code)

subroutine file_size(file,size,err_code)

character*20 file
integer size,err_code,number_of_records

if(err_code.eq.0)then

no_of_records=size/length_of_record

Where are we calclating err_code and size?

The length each record is 512.

25 Sep 2011 12:59 #9017

Hi Wilfred (or) anyone here,

Please can you advise?

Christy

25 Sep 2011 4:44 #9018

The subroutine file_size@(...) is part of the FTN95 library (see the '@' in the name)! 'File' is the name of your input file, 'size' and 'err_code' are return values. Size is given in bytes, and err_code = 0 means that everything was OK.

Regards - Wilfried

25 Sep 2011 11:31 #9019

Wilfred, thanks but I will be passing my code to a team who need to have it Fortran 77 -can you advise how to get this in Fortran 77?

25 Sep 2011 11:38 #9020

Wilfred, thanks but I will be passing my code to a team who need to have it Fortran 77 -can you advise how to get this in Fortran 77?

26 Sep 2011 8:20 #9021

I really don't know if there is a function in standard Fortran 77 to do what you want. Here is a very crude code you may use:

program test

implicit none

integer*4       i
character*120   ifile
character*512   string

ifile = 'test.ima'

     open(10,file=ifile,access='direct',recl=512,err=900)

     i = 10000
100  read(10,rec=i,err=110)string
     print*,'number of records: ',i
     goto 999
110  i = i-1
     goto 100

900  print*,'error opening file'
999  close(10)
end

Remarks: 'ifile' is your input file. You may change the line i = 10000 to a bigger number - it must be the maximum number of records your files can have.

Regards - Wilfried

26 Sep 2011 8:27 (Edited: 26 Sep 2011 9:33) #9022

... and here a little bit better with the subroutine you may need:

program test

implicit none

integer*4       i
character*120   ifile

ifile = 'test.ima'
call no_of_rec(ifile,i)
if (i .gt. 0) then
  print*,'number of records: ',i
else
  print*,'error'
end if
end

     subroutine no_of_rec(ifile,i)

     implicit none

     integer*4       i
     character*120   ifile
     character*512   string

     open(10,file=ifile,access='direct',recl=512,err=900)
     i = 999999
100  read(10,rec=i,err=110)string
     goto 999
110  i = i-1
     if (i .gt. 0) goto 100
900  i = -999
999  close(10)
     return
     end

Regards - Wilfried

26 Sep 2011 9:11 #9023

A binary search might be quicker, depending on the speed of a failed read. I've tested the following changes, assuming 512 byte records.

program test 
!
     character ifile *120
     integer*4 file_size_bytes, bytes
     external  file_size_bytes
!
     ifile = 'test.ima' 
!
     call create_file (ifile, 7213)
!
     bytes = file_size_bytes (ifile)
!
     write (*,fmt='(a,i0)') 'Number of bytes in file '//trim(ifile)//' = ', bytes
!
     end

     subroutine create_file (ifile, num)
!
!  create a file of 'num' records of 2048 bytes to test
!  demonstrates record size must only be multiple of 512 bytes
!
     character ifile*(*)
     integer*4 num, i
!
     open (10, file=ifile, access='direct', recl=512*4, iostat=i) 
     do i = 1,num
        write (10, rec=i) i
     end do
     close (10)
     write (*,*) trim (ifile),' created'
     end

     integer*4 function file_size_bytes (ifile)
!
!  determine number of 512 byte records in file
!  file record size must be a multiple of 512 bytes
!
     character ifile*(*)
!
     integer*4 good, bad, i
     character string*64 
!
     open (10, file=ifile, access='direct', recl=512, err=900) 
!
     good = 0
     bad  = 0
!
     do i = 1,huge(i)
        if (bad > 0) then              
           next = good + (bad-good)/2    ! split the difference
           if (next == good) exit
        else 
           next = max (good,512)*2       ! expand the search
        end if
        read (10,rec=next,err=110) string 
        print*,i, ' testing', next,' is ok'
        good = next
        cycle
110     bad  = next
        print*,i,' testing', next,' is bad'
     end do
!
     write (*,fmt='(a,i0,a,i0,a)') 'Number of records: ',good,' ( ',i,' tests )' 
     file_size_bytes = good*512
     goto 999 
!
900  print*,'error opening file' 
     file_size_bytes = -1
999  close (10) 
     end
Please login to reply.