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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Variable length sequential read

Status
Not open for further replies.

joeyc100

Programmer
Feb 1, 2011
15
US
Using MS Fortran 4.1, I am trying to read variable length formatted sequential records from a file. Each record is terminated by a CRLF. I set up a buffer of 1024 bytes (expected max), and want to read each record one-at-a-time, but I can't seem to properly set up the read and format statements to stop the read so as to avoid filling the buffer with additional records. The format appears to repeat until the buffer is filled.
Any advice?
Joey.
 
The way I'd normally do it is

1) Fill the buffer with spaces
2) Read the line into the buffer
3) Read from the buffer with an end= and err=

Could you show us how you're reading it?
 
character*1 buffer(1024)
...
...
data buffer/1024*'z'/ ( as a telltale to show how much has been read per read)
...
...
read(unit,100)buffer
100 format(1024a1)
...
....
I had thought that an EOR would stop the read with only the one record and the rest of the buffer would be z's, but it continues to read records to fill the buffer.
Joey.
 
Hi joeyc100

Try to define the buffer as a 1028 long string, instead of 1028 long single character vector as you do:

Code:
	Program XXX

	character*1028 buffer
	integer*4 lb

	do while(.true.)
	   do i=1,1028
	      buffer(i:i) = ' '
	   enddo
	   read(unit,'(a)',end=999) buffer
	   lb = len_trim(buffer)
	   write(*,'(1x,a)') buffer(1:lb)   ! write on screen
!	....
!	....
	enddo

999	continue
	end
 
As guilipe said, just read with '(A)' not with '(1028A1)'

It shouldn't matter if the buffer gets filled with spaces or Zs as long as it is not the data from the previous line.

eg if you have

123456789
456

What you don't want is 456456789
 
Thanks xwb,
I cannot understand gullipe's code. Apparently, my simple fortran code needs to be changed to something complex for the sake of "structural elegance". I am using MS fortran 4.1 and it doesn't appear to support this structure.

I will try using just the single A format and hope that it repeats to the point of the EOR, and no further. My concern is the fractional record that might occur if the one read fills the buffer. And then, where does the next read begin? If it begins at the second record, no harm done. But if it begins at what's left of the fractional record, then that record cannot be processed.
Jerry.
 
Using a FORMAT(A) results in the repetition of the edit descriptor; the buffer is filled until an EOF. The syntax of Aw where w is omitted results in a w equal to the number of chars in the iolist, in this case 1024. I'm still trying other things....
Thanks,
Joey.
 
Hi joeyc10

What kind of file are you reading? You say that your file contains "variable length formatted sequential records... Each record is terminated by a CRLF". This looks to me as a pure text file (*.TXT). If it is so, you should open it with only "OPEN(N,file='XXX.txt')", without specifying record length. Then each READ statement reads ONLY to the next CRLF, and you should use a string to read into (for instance 1024 charcter long) with format "A", as I do in the program above.
 
Yes, I am reading a .txt file with an open(unit,file='xxx.txt')
This defaults to sequential formatted with no record size.
Each read is reading to the iolist "length", and repeating the format(A) without stopping at the EOR. The key is the iolist, in this case buffer, which has no explicit count.
Joey.
 
Hi joeyc100

I guess that you have changed your program somewhat since your first post. How do the following statements look like now:

1) The declaration statement for "buffer" (or "length")
2) The open statement
3) The read statement
4) The format statement (if not included in the read statement)
5) The DO-loop to loop through all the TXT file.
 
There is no difference. I left out the OPEN statement.
CHARACTER*1 BUFFER(1024)
...
OPEN(UNIT,FILE='....')
...
READ(UNIT,100)BUFFER
100 FORMAT(1024A1)
...
WRITE(*,900)BUFFER
900 FORMAT(1X,1024A1)
...
I did trim the write statement to 128 chars so as not to fill the screen.

However, I just found out that even though the buffer is filled with each read, THE NEXT READ STARTS AT THE NEXT SEQUENTIAL RECORD!!!
Therefore I can ignore all the text beyond the first CRLF encountered in the buffer with each read, scan the record for it's size and process it.
I think this will do it. Thanks to all for their help.
Joey.
 
At first I thought you meant Powerstation 4.0 (c.1995) but MS never produced a Powerstation 4.1 because it became CVF so it must have been the previous version before the Visual stuff came along. Just curious as to which structure of gullipe's program your compiler did not support

The furtherst back I can go is MS Fortran 5.10 (c.1990) - that seems to accept long input lines
Code:
      program main
      integer BUFFMX, UNIT, LINES
      parameter (
     &   BUFFMX = 1024,
     &   UNIT = 10,
     &   LINES= 13)
      character*1024 buff
      integer line, col, ten
!
! set this to true if you wish to create the data
!
      if (.false.) then
!
! first write out the stuff
!
         open (UNIT, file = 'bigin.txt', status = 'UNKNOWN',
     &      form = 'FORMATTED')
         do line = 1, LINES
            buff = ' '
            ten = ichar('0')
            do col = 1, BUFFMX
               if (mod(col, 10) .eq. 0) then
	          buff(col:col) = char(ten)
                  ten = ten + 1
                  if (ten .gt. ichar('z')) ten = ichar('0')
	       else
	          buff(col:col) = char(line + 64)
               end if
            end do
            write (UNIT, '(A)') buff
         end do
         close (UNIT)
      end if
!
! Now try reading it back
!
      open (UNIT, file = 'bigin.txt', status = 'UNKNOWN',
     &   form = 'FORMATTED')
      do while (.true.)
         buff = ' '
         read (UNIT, '(A)', end = 999, err = 999) buff
         print *, len_trim(buff)
         print *, buff
      end do
999   continue
      close (UNIT)
!
      stop 
      end
The main difference is that I'm using character*1024 buff instead of character*1 buff(1024). If I then change the output section to use a character*1 buff(1024), I still get the same results.
Code:
      program main
      integer BUFFMX, UNIT, LINES
      parameter (
     &   BUFFMX = 1024,
     &   UNIT = 10)
      character*1 buff(1024)
!
! Now try reading it back
!
      open (UNIT, file = 'bigin.txt', status = 'UNKNOWN',
     &   form = 'FORMATTED')
      do while (.true.)
         buff = ' '
         read (UNIT, '(1024A1)', end = 999, err = 999) buff
         print '(1024A1)', buff
      end do
999   continue
      close (UNIT)
!
      stop 
      end
The main difference is that since it is an array of 1024 chars, the format needs to be 1024A1. If it was an 1024 character string, you can get away with A.
 
I am using MS Fortran 4.1 from 1987. As it is, my two lines of code (the Read and the Format) work fine. All of the excess data input beyond the CRLF can be ignored. The next read starts at the next sequential record which is correct. I was just confused by all the extra data input and afraid of partial records.

I don't believe in structuring Fortran such as to give it the appearance of C to keep the academic purists happy. Therefore I will stay with this archaic compiler because it is so much easier to work with. And as a bonus: a flow chart of the program in machine language is the same as a flow chart in this Fortran with all of its jumps and goto's, resp.
Thanks for your help,
Joey.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top