将位图格式(例如PNG)的绘图写入标准输出

时间:2019-01-22 13:30:29

标签: r plot stdout

是否可以让R将位图格式(例如PNG)的绘图写入标准输出?如果可以,怎么办?

具体地说,我想运行Rscript myscript.R | other_prog_that_reads_a_png_from_stdin。我意识到可以创建一个临时文件并使用它,但是这样做很不方便,因为该管道可能同时运行许多副本,因此需要选择唯一文件名并随后将其删除的方案。

到目前为止,我已经尝试设置outf <- file("stdout"),然后运行bitmap(file=outf, ...)png(filename=outf, ...),但是都抱怨(分别为'file' must be a non-empty character stringinvalid 'filename' argument),与这些功能的官方文档一致。

由于我能够说服R的read.table()函数从标准输入中读取内容,所以我希望有办法。我无法通过搜索[r] stdout plot或在stdout中将"standard output"替换为plot的任何变体形式(带或不带双引号)和/或png替换为{{1}}。

谢谢!

2 个答案:

答案 0 :(得分:5)

不幸的是,{grDevices}(并暗示{ggplot2})似乎从根本上不支持这一点。

解决此问题的明显方法是:让图形设备写入临时文件,然后将该临时文件读回到R会话并将其写入stdout。

但是这失败了,因为,一方面,数据不能读入字符串:R中的字符串不支持嵌入的空字符(如果尝试,则会出现诸如“不允许使用空字符”的错误) )。另一方面,readBinwriteBin失败是因为writeBin断然拒绝写入连接到stdout的任何设备,该设备处于文本模式(忽略在POSIX系统上,两者是相同的事实。

只能以令人难以置信的hacky方式来规避,例如by opening a binary pipe to a command such as cat

dev_stdout = function (underlying_device = png, ...) {
    filename = tempfile()
    underlying_device(filename, ...)
    filename
}

dev_stdout_off = function (filename) {
    dev.off()
    on.exit(unlink(filename))
    fake_stdout = pipe('cat', 'wb')
    on.exit(close(fake_stdout), add = TRUE)
    writeBin(readBin(filename, 'raw', file.info(filename)$size), fake_stdout)
}

要使用它:

tmp_dev = dev_stdout()
contour(volcano)
dev_stdout_off(tmp_dev)

在存在/dev/stdout的系统上(大多数是 ,但不是所有POSIX系统),可以通过删除命令重定向来稍微简化dev_stdout_off函数:

dev_stdout_off = function (filename) {
    dev.off()
    on.exit(unlink(filename))
    fake_stdout = file('/dev/stdout', 'wb')
    on.exit(close(fake_stdout), add = TRUE)
    writeBin(readBin(filename, 'raw', file.info(filename)$size), fake_stdout)
}

答案 1 :(得分:1)

这可能不是一个完整的答案,但这是我所能得到的最好的答案:您可以使用stdout()命令打开连接吗?我知道png()会将输出设备更改为文件连接,但这不是您想要的,因此将png替换为stdout可能会起作用。但是,我对标准输出的了解还不足以检验这一理论。

help page建议此连接可能是纯文本的。在这种情况下,一种解决方案可能是生成一个随机字符串以用作文件名,然后通过stdout传递文件名,以便管道中的下一步知道在哪里可以找到文件。