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

Stream

JohnNichols
Valued Contributor III
939 Views

Streams are useful in C#.  There is a post in https://fortranwiki.org/fortran/show/Stream+Input+Output  that gives the following code

 

 PROGRAM writeUstream
  IMPLICIT NONE
  INTEGER :: myvalue = 12345, mypos, out
  OPEN(NEWUNIT=out, FILE="ustream.demo", STATUS="UNKNOWN", ACCESS="STREAM")
  WRITE(out) "first"
  WRITE(out) "second"
  INQUIRE(UNIT=out, POS=mypos)
  PRINT *, "Myvalue will be written at position ", mypos
  PRINT *,myvalue
  WRITE(out) myvalue
  CLOSE(UNIT=out)
  END PROGRAM writeUstream

 

But the output file with both ifort and ifx is 

Screenshot_20230121_101827.png

I added a code to print the myvalue to the screen and it is correct, but the 90 is interesting.  Why 90?  I assume the nuls are some sort of end of file 

0 Kudos
7 Replies
mecej4
Honored Contributor III
932 Views

The decimal integer 12345 is the same as the default integer Z'00003039'. If you interpret the four bytes as characters, on a little-endian system, you would see '9', '0' and two NUL characters. No EOF marker there.

0 Kudos
JohnNichols
Valued Contributor III
906 Views

So to recover the original number I take 9 == ascii code 39 and 0 is ascii code 30 and nul is 0, so 00003039 and do a decimal and I get 12345. 

So you need to know the format of the numbers in advance.  

0 Kudos
Steve_Lionel
Honored Contributor III
898 Views

You did an unformatted write - it's just the memory representation of the 4-byte integer value 12345. 

0 Kudos
FortranFan
Honored Contributor III
895 Views

@JohnNichols ,

Re: "So to recover the original number ..  So you need to know the format of the numbers in advance," yes.  The `WRITE and `READ` operations need to use conforming form parameters for the IO unit and format descriptors.

Now, toward a format to create documents that will be more readily readable, you can look into `form="formatted"` option with STREAM IO - give the following a try and view the test.txt file in the file reader of your choice.

 

   integer :: lun
   open( newunit=lun, file="test.txt", access="stream", form="formatted", status="replace")
   write( lun, fmt=* ) "first", "second", 12345
end

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
863 Views

FF>>you can look into `form="formatted"

Or, you can format the numbers into character variables and WRITE those.

PROGRAM writeUstream
    IMPLICIT NONE
    INTEGER :: myvalue = 12345, mypos, out
    CHARACTER(len=80) :: line
    OPEN(NEWUNIT=out, FILE="ustream.demo", STATUS="UNKNOWN", ACCESS="STREAM")
    WRITE(out) "first"
    WRITE(out) "second"
    INQUIRE(UNIT=out, POS=mypos)
    PRINT *, "Myvalue will be written at position ", mypos
    PRINT *,myvalue
    WRITE(line,"(I)") myvalue
    line = adjustl(line)
    WRITE(out) trim(line)
    CLOSE(UNIT=out)
END PROGRAM writeUstream
...
type ustream.demo
firstsecond12345

*** Note, using STATUS="UNKNOWN", and with pre-existing file, will overstrike data contained within the file. IOW if the old file is larger than the new content, the resultant file will contain the residual data.

 

Jim Dempsey

 

0 Kudos
JohnNichols
Valued Contributor III
853 Views

I was interested in the article on streams at the wiki.  The article provided the simple example and I had a spare minute between being punished by a challenging problem with the Smithsonian Institution NUCs.  

I changed the new to unknown so I did not have to keep deleting the file, it was that or use an inquire and delete command.  

I should have twigged to the hexadecimal, I play with the a lot of that stuff with the ST.COM accelerometers and now the range finder.  The challenge with accelerometers is knowing the constants for the numerical integration of the results, so I started to play with a simple range finder, as usual the ST.COM software has some interesting limitations, solving those will take a few months, but I got the standard software running last night and left the thing running on my desk shooting at the ceiling. So the only movement is the roof from the weather, almost no wind and the change in temperature.  When I started the house was at 74 F and my daughter to sleep last night turned it down to 71.  The results for about 14 hours are shown in centimetres.  Just the way ST.COM do it, SI is so easy.  The left hand end is at 74 and by this morning the house is at 71, it is 44 outside so it cooled off not to slowly.  My house thermometer is F as is usual in the US.  

 

Screenshot_20230122_100533.png

A look at the early data shows 

 

Screenshot_20230122_100906.png

The data has a Gaussian element with a standard deviation of about 0.5 cm and a Fourier series of about 5 second period.  The range is to great for the data to be pure Gaussian and the house is not moving up and down through 7 cm.   Not great, but one can work with it.  

 

The problem is the standard program only gives you a CSV file that is open all the time, and has the format shown in the attached CSV file.  But I want to be able to read the latest data from the last line in the file, whilst it is still open and running.  Can I do that in Fortran?  

Note I know it can be done as NOTEPAD++ will open already open files.  

The other thing is, there are a significant number of people who read this forum, but very rarely post, the views count suggests this, I wonder if INTEL measure the IP of the visitors.  I would to tell the high and mighty how useful the site is to the community.  So providing some interesting Fortran stuff is well a community service.  (Ok, I am laughing at this one.) 

 

But a Fortran API to connect to the ST.COM devices would be extremely useful, one billion of the range finder devices has been sold in 7 years to about 42000 different companies.  

0 Kudos
jimdempseyatthecove
Honored Contributor III
842 Views

Try adding SHARED to the OPEN statement.

You may also need to add SHARE='DENYNONE' to the OPEN statement.

Note, the ST.COM program might not flush its I/O buffer after writes. In this case, the data might be delayed and/or you might see partial data.

You can use INQUIRE with SIZE=yourVariable to obtain the file size. Then use STREAM I/O to position at minimum, the worst case line size back from the file size. Then read into buffer and scan for next to last line terminator. What follows that should be the last line.

Jim Dempsey

0 Kudos
Reply