【问题标题】:Write unformatted (binary data) to stdout将未格式化的(二进制数据)写入标准输出
【发布时间】:2012-10-13 04:27:30
【问题描述】:

我想在 Fortran 90 程序中将未格式化(二进制)数据写入 STDOUT。我正在使用 AIX Unix,不幸的是它不会让我将第 6 单元打开为“未格式化”。我想我会尝试在不同的单元号下打开 /dev/stdout,但在 AIX 中不存在 /dev/stdout(尽管这种方法在 Linux 下有效)。

基本上,我想将我的程序输出直接传送到另一个程序中,从而避免有一个中间文件,有点像gzip -c 所做的那样。考虑到我上面遇到的两个问题,还有其他方法可以实现吗?

【问题讨论】:

  • FORTRAN unformatted 包含额外的标头数据,这使得它至少有些低效,更不用说如果您的接收程序也不是用 fortran 编写的,这很烦人。从这个角度来看,弗拉德米尔的回答(上半部分)可能就是要走的路。

标签: io fortran


【解决方案1】:

这更像是对@VladimirF 的评论/补充,而不是新的答案,但我还不能添加这些。您可以先查询预连接的 I/O 单元的位置,然后打开未格式化的连接:

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

这可能是最方便的方式,但它使用流访问,这是 Fortran 2003 的一个特性。没有这个,你只能使用顺序访问(给每条记录添加头数据)或直接访问(不添加头但需要固定的记录长度)。

【讨论】:

  • 一个好主意,但是在 AIX 下返回的文件名只是一个垃圾字符串。有趣的是,它可以在 Linux 中运行...
  • 哦,这很奇怪...这会依赖于编译器吗?我用的(gfortran和ifort)都没有问题,gfortran甚至提供了非标准的例程isattyttynam
  • 系统依赖,我猜。 AIX 在许多微妙而令人恼火的方面与 Linux 有点不同...
  • 适用于我的编译器。我只会使用output_unit 而不是 6 以获得更好的可移植性,但也许它没有意义,因为行为本身是不可移植的。 Fortran 2015 将允许在多个单元号下打开一个文件,但我不确定这些限制。
【解决方案2】:

我会尝试将 TRANSFER() 的数据转换为长字符并使用非高级 i/o 打印它。问题将是您的处理器对记录长度的限制。如果它太短,您最终会在某处出现意外的记录结束标志。此外,您的处理器可能不会按照您希望的方式写入不可打印的字符。

例如,类似

character(len=max_length) :: buffer

buffer = transfer(data,buffer)

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

我在不可打印字符中看到的最大问题。另见A suprise with non-advancing I/O

---编辑--- 另一种可能,尝试使用文件/proc/self/fd/1/dev/fd/1

测试:

open(11,file='/proc/self/fd/1',access='stream',action='write')
write(11) 11
write(11) 1.1
close(11)
end

【讨论】:

  • 谢谢 Vladimir:我喜欢你在 /proc 中使用文件描述符的第二个想法。我不想走 TRANSFER 路线,因为我有很多数据要写入,并且不想冒险达到记录长度的处理器相关限制。
  • 无需将所有数据都塞入一个缓冲区。使其大小合理并进行多次写入。你甚至可以使用一个小的缓冲区并写入单个值,尽管毫无疑问会有性能交易。
  • 这对我不起作用。有时它可以工作,但有些数据会损坏。如果缓冲区中有控制字符,它会正确写入吗?并阅读类似的transfer(buffer,data) 声明?
  • 你的代码是什么样子的?答案有 2 个选项。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-09
  • 1970-01-01
  • 2010-10-28
  • 2010-12-01
  • 2019-09-04
相关资源
最近更新 更多