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