Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Sequential WRITE with variable record length

holysword
Novice
417 Views

I have been trying to read and write some files in Fortran, but my knwoledge on IO is pretty limited. I have been opening the file with

OPEN(NEWUNIT=file_unit, FILE=filename, STATUS='replace', IOSTAT=file_status, &
                         ACTION='write', ACCESS='sequential', FORM="unformatted")

and writes are in a loop with

WRITE(file_unit, IOSTAT=file_status) var1,var2,var3...

That's all fine for writing and I get no errors. The problem is that I don't know the size of the records; the type of the variables var1 var2 and var3 MAY change between writes. When trying to read, I open the file in exactly the same way, but when I try to read

CHARACTER(LEN=1024) :: longbuf

(...)

READ(file_unit, IOSTAT=file_status) longbuf

I get IOSTAT=67 although it does read the file properly: It reads only "one record" and stores it in the longbuf variable. After going through all the records in the file it gives me the proper EOF IOSTAT which is -1.

My question is, am I doing this in the best way? What does the IOSTAT 67 stand for? I've seen that there is a IS_IOSTAT_EOF function in F2003, are there other similar intrinsic?

Thanks in advance!

0 Kudos
1 Solution
Steven_L_Intel1
Employee
417 Views

All of the IOSTAT values are documented - there's also IOMSG which will give you a text version. 67 is "Input statement requires too much data", which is what you get when you try to read a 1024 byte variable from a record that's shorter.

A basic problem you have is that unformatted I/O assumes that you know exactly what you're reading, since it's a straight transfer of bits. How were you planning to separate out the values if you read it into a string buffer?

Sequential unformatted I/O isn't really suitable to a program where the types and sizes of variables changes unpredictably with each WRITE. What you might be able to do is open the file ACCESS='STREAM' so that there is no record structure, and precede the variables with some sort of code that tells you what is to follow. When reading, read the code first, then choose an appropriate READ to get the values.

View solution in original post

0 Kudos
3 Replies
Steven_L_Intel1
Employee
418 Views

All of the IOSTAT values are documented - there's also IOMSG which will give you a text version. 67 is "Input statement requires too much data", which is what you get when you try to read a 1024 byte variable from a record that's shorter.

A basic problem you have is that unformatted I/O assumes that you know exactly what you're reading, since it's a straight transfer of bits. How were you planning to separate out the values if you read it into a string buffer?

Sequential unformatted I/O isn't really suitable to a program where the types and sizes of variables changes unpredictably with each WRITE. What you might be able to do is open the file ACCESS='STREAM' so that there is no record structure, and precede the variables with some sort of code that tells you what is to follow. When reading, read the code first, then choose an appropriate READ to get the values.

0 Kudos
holysword
Novice
417 Views

Steve Lionel (Intel) wrote:

All of the IOSTAT values are documented - there's also IOMSG which will give you a text version. 67 is "Input statement requires too much data", which is what you get when you try to read a 1024 byte variable from a record that's shorter.

A basic problem you have is that unformatted I/O assumes that you know exactly what you're reading, since it's a straight transfer of bits. How were you planning to separate out the values if you read it into a string buffer?

Sequential unformatted I/O isn't really suitable to a program where the types and sizes of variables changes unpredictably with each WRITE. What you might be able to do is open the file ACCESS='STREAM' so that there is no record structure, and precede the variables with some sort of code that tells you what is to follow. When reading, read the code first, then choose an appropriate READ to get the values.

I didn't have a very clear idea on how to split the data from a string buffer. Can't Fortran re-interpret a sequence of bytes regardless of the type it was assigned? 

In any case, your suggestion is far better. I am writing now it as a stream, and registering the type and kind of the variable that will follow. Works flawlessly, thanks!

0 Kudos
Steven_L_Intel1
Employee
417 Views

There are ways to "reinterpret" the type, but you have to know which type you want first. Furthermore, with sequential unformatted files you need to know in advance how many bytes you want to read from a record, which is why stream works better for your application.

0 Kudos
Reply