[comp.lang.fortran] Direct Unformatted I/O

brian@radio.astro.utoronto.ca (Brian Glendenning) (05/31/89)

I have a problem where I want to do direct unformatted i/o to a file,
where the record length isn't known until run-time, but a maximum
length is known. So I do something like:

      PARAMETER (BIG=1024)
      REAL LINE(BIG)
      READ (5,*) NSIZE
      OPEN ( [...] ACCESS='DIRECT', FORM='UNFORMATTED', RECL=NSIZE*4, [...])
      (4 is a constant that varies with hardware)

Now obviously I want to put NSIZE reals into LINE and write them out
later. My question is: what is the proper way to do  this. On our Sun
3 it looks like you fill up the last NSIZE elements of LINE and use a
write statement of the form:

            WRITE( [...] REC=[...]) LINE(BIG-NSIZE+1)

Is this the right thing to do in general? My recollection was that you
filled up the first  NSIZE elements of LINE, and used a line like:

            WRITE( [...] REC=[...]) LINE

and the fortran io would automatically take the appropriate number of
units of storage (RECL) from the beginning of line.

However, on our Sun 3 under 4.0 this isn't what happens, so probably
my recollection is faulty. So my question is: what is the standard
(portable) way to do this? Am I doing it right? Thanks.
--
--
	  Brian Glendenning - Radio astronomy, University of Toronto
brian@radio.astro.utoronto.ca uunet!utai!radio!brian  glendenn@utorphys.bitnet

maine@altair.dfrf.nasa.gov (Richard Maine) (05/31/89)

In article <BRIAN.89May31001207@radio.utoronto.ca> brian@radio.astro.utoronto.ca (Brian Glendenning) writes:

>  Now obviously I want to put NSIZE reals into LINE and write them out
>  later. My question is: what is the proper way to do  this. On our Sun
>  3 it looks like you fill up the last NSIZE elements of LINE and use a
>  write statement of the form:

>              WRITE( [...] REC=[...]) LINE(BIG-NSIZE+1)

This would write only a single element, not NSIZE of them.  Since the
file was opened for direct access with a record length corresponding
to NSIZE elements, this statement is illegal.  I suppose it is possible
that some implementation might fill up the record with succeeding
elements, but it is certainly neither portable nor standard.

>  Is this the right thing to do in general? My recollection was that you
>  filled up the first  NSIZE elements of LINE, and used a line like:

>              WRITE( [...] REC=[...]) LINE

>  and the fortran io would automatically take the appropriate number of
>  units of storage (RECL) from the beginning of line.

This asks to write the whole line array.  It is illegal and non-portable.
I have seen implementations that would fill up the record with the first
NSIZE elements (if you used err=... or iostat=... to get control back
after the error), but you cannot count on it.

The only portable way to do this is with an implied do loop as in

  WRITE( [...] REC=[...]) (LINE(I),I=1,NSIZE)

or something equivalent.  Hmm, forgot to mention one other approach,
somewhat more roundabout, using adjustable array dimensions in subroutines.

  CALL SUB(LINE,NSIZE)
  ...
  SUBROUTINE SUB(LINE,NSIZE)
  REAL LINE(NSIZE)
  ...
  WRITE( [...] REC=[...]) LINE
  ...

This is probably overly complicated unless it fits in naturally with
other program structure.
--

Richard Maine
maine@elxsi.dfrf.nasa.gov [130.134.1.1]