problem reading/writing binary direct access files

problem reading/writing binary direct access files

I've been given a program with this basic information:

integer*4 wind(10585,4,17)

    open(unit=8,file='swind.dat',form='unformatted',
     +        access='direct',recl=4*719780)

    write(8,rec=1) wind

It's taking a 3d array and writing it as a single record into the output file.  However the file it generates is 11 mb in size.  This program was run on UNIX (compiled by gcc) to generate the file and it was a little under 3mb in size.

I did check of the binary contents and noticed this.  The files are the same and then this file on the PC is padding a bunch of zeros afterward.  It's causing my program that reads this file to return zeros instead of numbers.

My reading program's open/write statements look like this where nbytes is 4*10585 or 42,340 and the irec variable is going from 29 to 44.

        open (unit=units(nextop),file=filename,status='old',
     &recl=nbytes,access='direct',iostat=istat,form='unformatted')

      read (iunit,rec=irec,iostat=istat) (wdata(i),i=1,mxrec)

I'm thinking since the PC version of this file is so much larger than the UNIX version, I'm guessing the writing Fortran program is doing something funny.  At the same time, I'm also surprised I'm not getting numbers back from the reading program because the first half of the PC and UNIX files are identical.

Is this a problem with the code or am I missing a compiler flag?  I just compiled this program without any additional flags when I created a console program.

publicaciones de 7 / 0 nuevos
Último envío
Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.

The units of recl vary between compilers.  By default with ifort it is in four byte words (4 x ~ 3MB = ~12 MB !).  gfortran uses byte units.

You can change ifort to use bytes units by using the /assume:byterecl compiler option.  Recent Fortran standards recommand that the units of RECL be bytes (hence /standard-semantics includes /assume:byterecl), but I could imagine lots of users getting rather cranky if the long standing default for ifort and its ancestors was changed. 

You can use an INQUIRE statement with an IOLENGTH specifier to determine the required record length for a particular list of io-items that removes the need to know the units of RECL in advance.  This is robust practice.

With the mismatch in RECL between the write and the read, you are implicitly relying on the compiler using a particular on-disk structure for its direct access, unformatted files (a structure that doesn't store record lengths in any way).  This assumed structure is pretty common, but it is not required by the Fortran standard (ifort will use a different structure that breaks your assumption with certain compiler command line options).  I suggest that a clearer and more robust arrangement would be to write the array out in the same manner that you read it (same RECL, same number of records).  Alternatively, use unformatted, stream access, and for reading do the equivalent to record positioning yourself using the POS specifier.  The size of a file storage unit under stream access could technically not be a byte, but all the compiler authors that ever wanted to choose something different have now been safely locked up in secure institutions.

Ian,

I tried to recompile the writing code with /assume:byterecl.  However when I reran the new executable, the output file was still the same size.  It did not get any smaller.  That should have worked without me having to change the code, shouldn't it?

Sorry forgot to mention that on the receiving or reading end:

integer wtdata(1439560)
parameter (mxrec = 10585)

So the fact that I wrote it initially as a 3d array and am now reading it as a 1d array is the reason it's unhappy?

Delete the output file before you rerun the program compiled with the /assume:byterecl option, or consider adding the STATUS='REPLACE' specifier on the OPEN statement.

Hmm...

Good news:  The file shrunk down to 2.8 mb on the writing end

Bad news:  The reading end is now giving an iostat(36) error when it's trying to read the file.

Did you recompile the reader with /assume:byterecl?

Narf! @$%@#@#$@#!!!!

Thank you Ian.  Everybody is happy now.

Deje un comentario

Por favor inicie sesión para agregar un comentario. ¿No es socio? Únase ya