Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Format error in reading numbers

Shrinivassan_R_
Beginner
2,064 Views

When the below command executes, it read the file content (    35) where all the spaces are ignored and it reads only the numbers in that case the size of the number is only 2 bytes, but we are trying to read 8 byte number which throws the exception.

 

FORMAT(I8)


IF I use FORMAT(I2) then there is no exception

 

      program test

 

 

      INTEGER(4) IRATE

 

      OPEN(4,file='C:\Srini\Files\Arat51',status='OLD',access='DIRECT',

     &               form='FORMATTED',recl=8)

 

 

      Read(4,200,rec=2)IRATE

 

      CLOSE(4)

 

200   FORMAT(I8)

 

      STOP

      end

 

0 Kudos
1 Solution
mecej4
Honored Contributor III
2,044 Views

With your data file, the following program works correctly if I specify RECL=10 in the OPEN statement, with the data file containing CR+LF at end-of-line. Similarly, with the datafile using LF for EOL, using RECL=9 in the OPEN statement gives correct output.

      program test
      INTEGER(4) IRATE,i
!
      OPEN(4,file='Arat51',status='OLD',access='DIRECT',
     &               form='FORMATTED',recl=10)
      i=2
      DO while(i .le.16)
         Read(4,200,rec=i)IRATE
         write(*,*)i,irate
         i=i*2
      end do
      CLOSE(4)
200   FORMAT(I8)
      STOP
      end

 

View solution in original post

0 Kudos
23 Replies
Arjen_Markus
Honored Contributor I
1,884 Views

Using _formatted_ direct access files is rather unusual. (Most of the time direct access files are unformatted, that is, raw bytes are stored, not human-readable numbers). As you set the record length to 8, it may be that the last one or two positions in these records are actually reserved for carriage-return/linefeed characters. This means that you format is simply too wide. Using a format I2 instead of I8 means that the read action stays well within the record and can therefore proceed.

What is the reason for using this kind of files? There may very well be an easier-to-use alternative. For instance: simply a sequential file.

What is the error message you get?

 

0 Kudos
Shrinivassan_R_
Beginner
1,884 Views

The file content looks like,

  131072
      35
      35
     852
     916
     986
    1064
     979
     989
     999
    1011
    1023
    1037
    1051
       0
       0
       0
       0
       0

 

The  error we get for this is  forrtl: severe (64): input conversion error

 

0 Kudos
Arjen_Markus
Honored Contributor I
1,884 Views

You could try reading it like this:

integer :: ierr

open( 4, file = '... proper name ...' )

do 
    read( 4, *, iostat = ierr ) irate
    if ( ierr /= 0 ) exit
enddo 

close( 4 ) 

So rather than opening it as a direct access, use the default. Instead of a specific format, use list-directed reads (the *). While it is not completely safe (see below), it is more flexible and as you open it as a sequential file, the lines may be any length.

(Safety of list-directed reading: a list-directed read will read on until all items in the read statement could be read or an error occurred. There are a few more rules that might bite you, although I have seldom seen them in practice. If you really need to read the file line by line, then use :

character(len=10) :: line

read( 4, '(a)', iostat = ierr ) line
read( line, * ) irate

with appropriate changes to fit in the code above)

0 Kudos
Shrinivassan_R_
Beginner
1,884 Views

The read statement in real time code will be like READ(4,200,rec=IPOS)IRATE, where IPOS will have the line number from where the data needs to be taken from file.

so I cant change the existing logic..:(

The same code works well in win Xp Compaq visual Fortran compiler but in Win 7 Intel visual Fortran its throws the error.

0 Kudos
Arjen_Markus
Honored Contributor I
1,884 Views

I tried this in a small program: using a file with records of numbers like 12345678.

When I open the file with a record-length of 8, then the first record is read correctly, but the second causes an input conversion error.

However, if I open the file with record-length 10 (to explicitly include the carriage-return/linefeed bytes), it works fine. My guess is therefore that Compaq Fortran automatically corrected for the extra bytes and that Intel Fortran does not. (The record-length of 10 bytes works fine with gfortran too)

 

0 Kudos
Shrinivassan_R_
Beginner
1,884 Views

The below code works fine but it reads the first line, how can I make it as by entering the line number ti should read
 

{code}

character(len=10) :: line

read( 4, '(a)', iostat = ierr ) line
read( line, * ) irate

{code}

 

 

0 Kudos
Arjen_Markus
Honored Contributor I
1,884 Views

See my other answer - you seem to require genuine direct access. I think the record length is wrong

0 Kudos
Shrinivassan_R_
Beginner
1,884 Views

The below command fails but if I use rec=1 no error the first line executes..

read( 4, '(a)',rec=3, iostat = ierr ) line

I am new Fortran please help..

 

0 Kudos
Arjen_Markus
Honored Contributor I
1,884 Views

I understand that you are new to Fortran, but it would help if you provide enough information:

  • How does it fail? What is the error message?
  • How do you open the file?
  • Better still: Can you post the complete program?

Note my previous post - about the record length - my guess is that it should be 10 not 8.

0 Kudos
mecej4
Honored Contributor III
2,045 Views

With your data file, the following program works correctly if I specify RECL=10 in the OPEN statement, with the data file containing CR+LF at end-of-line. Similarly, with the datafile using LF for EOL, using RECL=9 in the OPEN statement gives correct output.

      program test
      INTEGER(4) IRATE,i
!
      OPEN(4,file='Arat51',status='OLD',access='DIRECT',
     &               form='FORMATTED',recl=10)
      i=2
      DO while(i .le.16)
         Read(4,200,rec=i)IRATE
         write(*,*)i,irate
         i=i*2
      end do
      CLOSE(4)
200   FORMAT(I8)
      STOP
      end

 

0 Kudos
Shrinivassan_R_
Beginner
1,884 Views

Thank you very much.. by changing the  recl value to 10 (recl=10) the code worked without any exception...

Will implement the same in the live code..

but can you guide what is the use for recl? why do we need to change it to 10?

0 Kudos
mecej4
Honored Contributor III
1,884 Views

One explanation is that the value specified with RECL= is used to map record number to the byte offset in the file. Since Windows and Unix have a simple notion of a file as a collection of bytes, the old mainframe record-oriented file types have to be simulated.

Thus, if you have a file with 8 characters per line, and CR+LF as end-of-line, Rec-1 is at byte 0, Rec-2 is at byte 10,..., and Rec-n is at byte (n-1)*10.

There is a keyword to help with record sizes; use an IOLENGTH= clause in an INQUIRE statement on the file.

0 Kudos
Shrinivassan_R_
Beginner
1,884 Views

Hi,

Therese was one more error in another file,

program test2

 

 

INTEGER(4) IPOS

INTEGER*4 TBDATE(3),IEFFDT

DIMENSION ITB(0:3)

INTEGER IYEVT,IMEVT,IENTRY,ITERM

integer :: ierr

OPEN(4,file='File1',status='OLD',SHARE='denywr',

& access='DIRECT',form='FORMATTED',recl=48)

READ(4,900,REC=1557)IPOS,IEFFDT,IYEVT,IMEVT,IENTRY,ITERM,

& (ITB(I),I=0,3)

CLOSE(4)

 

900 FORMAT(I4,I9,I5,I2,I5,I3,4I5)

 

stop

end

 

The File content looks like,

1548 20170201 2029 8 2010 19   15  -11   15   41
1549 20170201 2029 8 2011 18   13  -12   13   37
1550 20170201 2029 8 2012 17   11  -12   11   34
1551 20170201 2029 8 2013 16    8  -13    8   30
1552 20170201 2029 8 2014 15    5  -14    5   25
1553 20170201 2029 8 2015 14    2  -15    2   19
1554 20170201 2029 8 2016 13   -2  -17   -2   12
1555 20170201 2029 8 2017 12    0    0    0    0
1556 20170201 2030 8 1985 45   28  -19   28   75
1557 20170201 2030 8 1986 44   26  -20   26   71

I tried changing the recl values but still exception is thrown

 

 

0 Kudos
Arjen_Markus
Honored Contributor I
1,884 Views

Well, the problem seems to be the same thing: a mismatch between the actual length of the records in the file and the length that you specify in the program. If you carefully count the number of positions expected by the format, you get to 48. The length specified. But as before, you need to also include the invisible bytes. So use a length of 50.

0 Kudos
Shrinivassan_R_
Beginner
1,884 Views

I changed the length to 50 but still there is an exception..  I even changed it 80 but the same exception are thrown.

 

0 Kudos
Arjen_Markus
Honored Contributor I
1,884 Views

You should be aware that this is a very fragile way of working: if the length of the records in the file is not constant, it will fail, since the bytes that are read critically depend on the length that you give. Even as much as a single additional byte or a single byte not present (a space for instance) will cause problems.

It makes no sense to set the record length to, say, 80, because, unlike with sequential files, there is NO flexibility. Your record length in the program must match exactly the record length in the file. Down to the last invisible byte.

Is it possible to change the program that produces these files? For instance to have it write _unformatted_ direct-access files?

Your only hope is to examine the input file byte by byte. If - and ONLY if - every record has the same length, the method you have been using will work with that length. Here is a small Fortran program that you can use:

! chkfile.f90 --
!     Read a (text) file byte by byte and report the perceived record length
!
program chkfile
    implicit none

    integer          :: ierr, length, recno
    character(len=1) :: byte

    open( 10, file = 'example.inp', access = 'stream' )

    recno  = 0
    length = 0
    do
        read( 10, iostat = ierr ) byte

        if ( ierr /= 0 ) then
            exit
        endif

        length = length + 1
        if ( byte == achar(10) ) then
            recno = recno + 1
            write( *, '(a,i5,a,i10)' ) 'Length of record', recno, ': ', length
            length = 0
        endif
    enddo
endprogram

 

0 Kudos
mecej4
Honored Contributor III
1,884 Views

Shrinivassan R. wrote:
I changed the length to 50 but still there is an exception..  I even changed it 80 but the same exception are thrown.

You need to know the structure of your data files precisely, if you wish to access them as fixed-record-length direct-access files. Willy-nilly changing of the RECL value in the OPEN statement will just waste time.

Here is a modified version of the code in #11 to read the data file displayed in #14:

      program test
      INTEGER ISEQ,cdate,cyr,n,eyr,i,i3(5)
!
      OPEN(14,file='r48.txt',status='OLD',access='DIRECT',
     &               form='FORMATTED',recl=50)
      i=2
      DO while(i .le.8)
         Read(14,200,rec=i)iseq,cdate,cyr,n,eyr,i3
         write(*,*)i,iseq,cdate,cyr,n,eyr,i3
         i=i*2
      end do
      CLOSE(14)
200   FORMAT(I4,I9,I5,I2,I5,I3,4I5)
      STOP
      end

I used a record length of 50 precisely because the data has 48 'payload' characters per line/record and I stored the file as a CR+LF text file.

0 Kudos
Shrinivassan_R_
Beginner
1,884 Views

Thanks a million.. It worked:)

 

0 Kudos
garylscott1
Beginner
1,884 Views

Something doesn't seem quite right.  The user should never need to specify a record length that includes compiler added record structure content, especially for direct access (e.g. the leading and trailing length value that some compilers add to emulate fixed length records on "real" OS').  The user should only need to define the "data" content.  Record structure added content should be assumed by the compiler based upon the specified open parameters.

0 Kudos
mecej4
Honored Contributor III
1,570 Views

I agree that having to add the byte count of the EOL to the record size makes me uncomfortable, too. I did spend a few minutes reading through sections of the F2003 standard to pin this issue down, but failed.

On the other hand, many record-type files are not portable (say, from ZOS to VMS or Unix), so perhaps one should not expect the standard to go into "implementation details".

Such discrepancies probably motivated the creation of HDF and CDF files.

0 Kudos
Reply