[comp.lang.fortran] Fortran OPEN and WRITE

jliu@hpuxa.ircc.ohio-state.edu (Joe Liu) (04/08/90)

   I have been troubled by maybe a very simple problem, what I 
want to do is:   to write a collection of data into a binary file, 
each of my data is normalized to 128 ( 1-128), so it's possible to 
represent it with a BYTE on VAX or INTEGER*1 on a Stellar UNIX machine.
Now I must write the data byte by byte successively, because that's how
another program will look for data.  Suppose I have 5 data points as
( 1,2,3,4,5), the binary file I want must be 5 bytes.  However, it seems
Fortran on the Unix takes 1+8 bytes to write each one byte data, thus
the following will result in a 45 bytes file.  

        OPEN (7, FILE='test.dat', FORM='UNFORMATTED')
        DO 10 I=1,5
  10    WRITE (7) I
        CLOSE (7)

 if I have a 5 bytes array and write the array as one record, I will 
get a 5+8= 13 bytes file on the Unix machine.  

         BYTE N(5)
         DO 10 I=1,5
  10     N(I)=I
         OPEN (7,FILE='test.dat, FORM='UNFORMATTED')
         WRITE (7) N
	 CLOSE (7)

  I can look at the 45 bytes or ( 13 bytes) file byte by byte, and I can 
see the first 4 bytes and the last 4 bytes contain some kind of information.
(the size of that record ? ) while the 5th byte contain the right data.
that is, in the 45 bytes files, the 45 bytes are,    
        0,0,0,1, 1 ,0,0,0,1
	0,0,0,1, 2, 0,0,0,1
	0,0,0,1, 3, 0,0,0,1
	0,0,0,1, 4, 0,0,0,1
 	0,0,0,1, 5, 0,0,0,1

 in the 13 bytes file, they are
      0,0,0,5, 1,2,3,4,5, 0,0,0,5 

Although Fortran has no problem to get the right data back when I read 
them out,   The file is not what I must have,  ie, only 1,2,3,4,5 in it.

  On the VAX machine, the bahavior is similar, only difference is that 
it has a 4 bytes extra for each record writen instead of 8.  If I compile
the above two on the VAX I will get a 25 bytes and a 9 bytes file respectively  
instead the 45 bytes and 13 bytes.

   I did try to play with possible options in the OPEN statements
but did not achieve what I wanted.  As I said the FORTRAN itself has 
no problem to read back the right data.  What's behind this ?  Some 
one told me this will not happen on an IBM machine but I did not get 
the chance to try it on IBM yet.  The same purpose can be very easily
achieved in C. That's what I am doing now, use a C program to pick out
the right bytes from a FORTRAN output and write it into the byte by byte
form, to input this into anthoer  graphics application. It will
be nice if I can slightly modify the FORTRAN program to have the compatible
output for the application.

   There must be a lot FORTRAN experts on this group. Please enlighten 
me.  I have sought help from as close as my next door to as far as DEC
technical assitance.  But I still do not know how.

 Thanks.            

Joe 

ggw@wolves.uucp (Gregory G. Woodbury) (04/09/90)

In article <962@nisca.ircc.ohio-state.edu> (Joe Liu) writes:
>   I have been troubled by maybe a very simple problem, what I 
>want to do is:   to write a collection of data into a binary file, 
:
>  However, it seems
>Fortran on the Unix takes 1+8 bytes to write each one byte data, thus
>the following will result in a 45 bytes file.  
>
>        OPEN (7, FILE='test.dat', FORM='UNFORMATTED')
>        DO 10 I=1,5
>  10    WRITE (7) I
>        CLOSE (7)
   This code generates 5 different records.  Each record contains a byte
count at the front and back to allow the BACKSPACE statement to work
on the file.

> if I have a 5 bytes array and write the array as one record, I will 
>get a 5+8= 13 bytes file on the Unix machine.  
>
>         BYTE N(5)
>         DO 10 I=1,5
>  10     N(I)=I
>         OPEN (7,FILE='test.dat, FORM='UNFORMATTED')
>         WRITE (7) N
>	 CLOSE (7)
    This code generated one record.  A WRITE statement will generate (at least)
one record for each call.  A formatted write can generate multiple records
by using the "/" format descriptor.

>Although Fortran has no problem to get the right data back when I read 
>them out,   The file is not what I must have,  ie, only 1,2,3,4,5 in it.
>
>  On the VAX machine, the bahavior is similar, only difference is that 
>it has a 4 bytes extra for each record writen instead of 8.  If I compile
>the above two on the VAX I will get a 25 bytes and a 9 bytes file respectively
>instead the 45 bytes and 13 bytes.
	On the VAX the record counts are limited to a smaller size and
only encode the count in a two-octet field.

>   I did try to play with possible options in the OPEN statements
>but did not achieve what I wanted.  As I said the FORTRAN itself has 
>no problem to read back the right data.  What's behind this ?  Some 
>one told me this will not happen on an IBM machine but I did not get 
>the chance to try it on IBM yet.

	IBM has been known to ignore documented standard behaviour
before.. ;-)
	Actually, in the IBM world, the UNFORMATTED form file is still
subject to the mainframe environments storage formats, which require you
to tell the OS the size of the record.  If you DD the file with a variable
record length, the OS i/o services hide the byte counts from the program.
It only looks like there are no record counts in the file.
	To turn the history back into its correct order...
	The bahaviour of FORTRAN UNFORMATTED WRITE under Unix and VAX/VMS
is a deliberate simulation of the variable record formats used in the older
mainframe FORTRAN environments.

> The same purpose can be very easily
>achieved in C. That's what I am doing now, use a C program to pick out
>the right bytes from a FORTRAN output and write it into the byte by byte
>form, to input this into anthoer  graphics application. It will
>be nice if I can slightly modify the FORTRAN program to have the compatible
>output for the application.

	Assuming that there is no way to modify the graphics application,
this is one of several potential solutions.  You probably do not want to modify
the fortran compiler or i/o library to change the unformatted i/o format.
	Other potential solutions:
	1.  Write a C subprogram to open the file, do the i/o and close
the file.  The interface between C and FORTRAN is well documented in
several places (or should be ;-).  This is the solution I have used several
times.
	2.  I have heard that there is a way of telling some Unix FORTRANs
to open a file as DIRECT access with a record length of ONE (1) and this
allows you to perform certain simulations of simple stream i/o.  I haven't
tried this, but it was mentioned in an AT&T F77 Reference Manual (with some
other caveats that I don't remember.)  Since the AT&T and BSD stock F77's
are still pretty much the same beast, I suspect that this trick, once
perfected, should be pretty portable.

>   There must be a lot FORTRAN experts on this group. Please enlighten 
>me.  I have sought help from as close as my next door to as far as DEC
>technical assitance.  But I still do not know how.
	Just play around, I think there should be some useful information
in the above ramblings.
> Thanks.            
>Joe 
	Your welcome.

-- 
Gregory G. Woodbury
Sysop/owner Wolves Den UNIX BBS, Durham NC
UUCP: ...dukcds!wolves!ggw   ...dukeac!wolves!ggw           [use the maps!]
Domain: ggw@cds.duke.edu  ggw@ac.duke.edu  ggw%wolves@ac.duke.edu
Phone: +1 919 493 1998 (Home)  +1 919 684 6126 (Work)
[The line eater is a boojum snark! ]           <standard disclaimers apply>

sjc@key.COM (Steve Correll) (04/10/90)

In article <962@nisca.ircc.ohio-state.edu>, jliu@hpuxa.ircc.ohio-state.edu (Joe Liu) writes:
>    I have been troubled by maybe a very simple problem, what I 
> want to do is:   to write a collection of data into a binary file...
> Suppose I have 5 data points as
> ( 1,2,3,4,5), the binary file I want must be 5 bytes.  However, it seems
> Fortran on the Unix takes 1+8 bytes to write each one byte data...

The Fortran 77 standard requires that the compiler's runtime system be able to
open a "sequential" access file without any prior knowledge of record lengths,
and then skip forward (using "read" with an empty list of data items) or
backward (using "backspace") over each record. To do this, the compiler must
be able to find out the length of each record.

If the host operating system provides variable-length-record files as a
built-in service of its file system, then the compiler may be able to ask the
operating system about the length of a record, and thereby avoid storing them
in the user-visible portion of the file.

Many systems (Unix, for example) do not provide this service, and therefore the
compiler's runtime system must simulate variable length records by storing the
record lengths inside the file. Even some systems which do provide variable
length records provide them in a form which doesn't exactly meet Fortran's
needs.

If you use "direct" access (as described in the Fortran 77 standard) then you
must specify a record length in the "open" statement, and most compilers will
use that instead of storing the record length in the file itself; this will
solve your problem so long as every record can be the same length, or can be
padded to the same length.
-- 
...{sun,pyramid}!pacbell!key!sjc 				Steve Correll