4

I want to write unformatted (binary) data to STDOUT in a Fortran 90 program. I am using AIX Unix and unfortunately it won't let me open unit 6 as "unformatted". I thought I would try and open /dev/stdout instead under a different unit number, but /dev/stdout does not exist in AIX (although this method worked under Linux).

Basically, I want to pipe my programs output directly into another program, thus avoiding having an intermediate file, a bit like gzip -c does. Is there some other way I can achieve this, considering the two problems I have encountered above?

M. S. B.
  • 28,968
  • 2
  • 46
  • 73
ccbunney
  • 2,282
  • 4
  • 26
  • 42
  • FORTRAN unformatted contains extra header data which makes it at least somewhat inefficient, not to mention annoying if your receiving program isn't also written in fortran. Vladmir's answer (top part) is likely the way to go just from that point of view. – agentp Oct 23 '12 at 11:56

2 Answers2

2

I would try to convert the data by TRANSFER() to a long character and print it with nonadvancing i/o. The problem will be your processors' limit for the record length. If it is too short you will end up having an unexpected end of record sign somewhere. Also your processor may not write the unprintable characters the way you would like.

i.e., something like

character(len=max_length) :: buffer

buffer = transfer(data,buffer)

write(*,'(a)',advance='no') trim(buffer)

The largest problem I see in the unprintable characters. See also A suprise with non-advancing I/O

---EDIT--- Another possibility, try to use file /proc/self/fd/1 or /dev/fd/1

test:

open(11,file='/proc/self/fd/1',access='stream',action='write')
write(11) 11
write(11) 1.1
close(11)
end
  • Thanks Vladimir: I like you 2nd idea of using the file descriptors in /proc. I don't want to go down the TRANSFER route though as I have a lot of data to write and dont want to risk hitting a processor dependent limit for record length. – ccbunney Oct 24 '12 at 08:37
  • there is no need to stuff all the data into one buffer. Make it a reasonable size and do multiple writes. You can even use a small buffer and write single values, though no doubt there is a performance trade. – agentp Oct 24 '12 at 12:53
  • This isn't working for me. Sometimes it works, but with some data it gets corrupted. If there are control characters in buffer, will it write correctly? And read with similar `transfer(buffer,data)` statement? – Jason Jul 13 '13 at 22:30
  • How does your code look like? There are 2options in the answer. – Vladimir F Героям слава Jul 14 '13 at 09:40
1

This is more of a comment/addition to @VladimirF than a new answer, but I can't add those yet. You can first inquire about the location of the preconnected I/O units and then open the unformatted connection:

character(1024) :: stdout
inquire(6, name = stdout)
open(11, file = stdout, access = 'stream', action = 'write')

This is probably the most convenient way, but it uses stream access, a Fortran 2003 feature. Without this, you can only use sequential access (which adds header data to each record) or direct access (which does not add headers but requires a fixed record length).

sigma
  • 2,758
  • 1
  • 14
  • 18
  • A nice idea, but the filename returned under AIX is just a garbage string. Interestingly, it works in Linux though... – ccbunney Oct 24 '12 at 08:44
  • Oh, that is strange... Would this be compiler dependent? The ones I use (gfortran and ifort) have no issues with it, and gfortran even provides the non-standard routines `isatty` and `ttynam`. – sigma Oct 24 '12 at 12:43
  • System dependant, I would guess. AIX is a bit different from Linux in many subtle and infuriating ways... – ccbunney Oct 25 '12 at 15:51
  • Works well with my compilers. I would just use `output_unit` instead of 6 for better portability, but maybe it is pointless, because the behaviour itself is non-portable. Fortran 2015 will allow one file to be opened under multiple unit numbers, but I am not sure about the restrictions. – Vladimir F Героям слава Jun 27 '17 at 14:37