This 开发者_开发技巧is somewhat related to my recent post about Fortran stream and the like: Converting data stored in Fortran 90 binaries to human readable format.
I am attempting to write a simple array of integers to a file, and then use Fortran's READ
function to then read in the binary that I have created. I am using stream by including ACCESS="STREAM"
in my OPEN
directive. I have the following code:
MODULE streamtest2subs
IMPLICIT NONE
CONTAINS
SUBROUTINE writeUstream(myarray)
IMPLICIT NONE
INTEGER, INTENT(IN), DIMENSION(4,10) :: myarray
INTEGER :: myvalue = 12345, mypos
OPEN(UNIT=11, FILE="ustream.demo", STATUS="REPLACE", ACCESS="STREAM")
WRITE(11) myarray
CLOSE(UNIT=11)
END SUBROUTINE writeUstream
SUBROUTINE readUstream
IMPLICIT NONE
INTEGER :: test1, test2, test3
INTEGER :: n
OPEN(UNIT=42, FILE="ustream.demo", STATUS="OLD", ACCESS="STREAM")
READ(42, POS=1) test1
READ(42, POS=2) test2
READ(42, POS=3) test3
WRITE(*,*) "This is the output:"
WRITE(*,*) test1
WRITE(*,*) test2
WRITE(*,*) test3
END SUBROUTINE readUstream
END MODULE streamtest2subs
PROGRAM streamtest2
USE streamtest2subs
IMPLICIT NONE
INTEGER :: i, j, k
INTEGER, DIMENSION(4,10) :: a
WRITE(*,*) "This is my input array:"
k=1
DO i=1,4
DO j=1,10
a(i,j)=k
WRITE(*, "(i3)", ADVANCE="NO") a(i,j)
k=k+1
END DO
WRITE(*,*)
END DO
WRITE(*,*)
CALL writeUstream(a)
CALL readUstream
END PROGRAM streamtest2
However, when I compile this using gfortran and run it, I get the following output:
This is my input array:
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
This is the output:
1
184549376
720896
Why is it that the output is so complex? Is it that READ
is reading the ustream.demo file as a string instead of as an integer? However, when I change the type of test1, test2, and test3 to string, my output is simply a series of three blank lines.
Am I using the POS
directive in READ
incorrectly? I think that POS
specifies the character number in the output (although I am not sure if the elements of the array are delimited in any way); is this correct?
Thank you very much for your time!
For the purposes that you have described in your previous question, I think that you are programming this more complicated than is necessary. Assuming that you want a binary file without extra record structure, you want unformatted and stream. You can read the file in the same way that you wrote it -- you don't need to use POS -- unless the purpose is to learn how to use POS.
My tested example is based on a Fortran program in which I read a binary file that was written by someone else, almost certainly with a C program. The file consists of headers, followed by arrays of variable lengths. I open the file:
open ( unit=75, file=FileName, status='old', access='stream', form='unformatted', action='read' )
I read a header (a variable that is a user-define type with many sub-variables):
read (75) header
I allocate the array to the length that was read into one field of the header, then I read the array:
allocate ( array (1:header % ArrayLen) )
read (75) array
Then I process the data in the array. Then I repeat until end of file (not shown in the code samples).
Very easy ... no need to calculating position in the file and use the POS keyword of READ.
The problem is your read statements, the POS
is the byte offset from the start of the file and is not related directly to the array index of the original a
array that was written to the file.
So, in your code if test1
is a 4 byte integer the Fortran read will construct it by reading bytes 1 to 4 of the file. Similarly, test2
would be constructed from bytes 2 to 5, whereas the value is actually stored in bytes 5 to 8.
When I change the read lines to,
READ(42, POS=1) test1
READ(42, POS=5) test2
READ(42, POS=9) test3
The output becomes,
This is my input array:
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
This is the output:
1
11
21
which I think is more what you were after. Note that if the values were written to file originally as, say, 2-byte or 8-byte integers then you would have to account for those sizes in the POS
offsets when you read the file.
As an aside, it's worth learning the command line tool od
for quick interrogations of binary files. For example, the first thing I did was check the write worked okay using,
$ od -t d4 ustream.demo
0000000 1 11 21 31
0000020 2 12 22 32
0000040 3 13 23 33
0000060 4 14 24 34
0000100 5 15 25 35
0000120 6 16 26 36
0000140 7 17 27 37
0000160 8 18 28 38
0000200 9 19 29 39
0000220 10 20 30 40
0000240
精彩评论