1

I believe this question has been asked for almost all languages except for R.

Essentially I'd like to check if stdin() is empty but I do not know how to do it.

This is because if you perform the following bit of code your session will hang (probably until something is sent to the relevant R process).

input <- file("stdin", "r")
result <- readLines(input, 1) # Session hangs here

Ideally, I could check the status of input before I try to read anything from it.

WARNING

If you run the above script then you will likely need to kill the running process wherever it lives (either interactively in some IDE or in an Rscript).

EDIT

I found a helpful SO post that shed some light on the situation. In summary you can use CTRL + D to signal end of file condition to the input (so far working for readLines(input, -1).

My ultimate goal is to write an Rscript that could accept input from a stdin connection via a pipe. However as I have discovered, the R interpreter will wait until it receives an end of file condition before returning. In the event nothing is actually piped into stdin, is there a way to programatically call this signal?

Justin Landis
  • 1,981
  • 7
  • 9
  • I can't reproduce the issue running R from a shell. Or maybe I don't understand the issue? After calling `readLines`, I can type into `stdin`. Hitting Return closes the connection and `readLines` returns the typed characters as a string. What behaviour are you expecting? – Mikael Jagan Mar 03 '22 at 05:51
  • If your R process hangs when running R from a GUI, then maybe you should be doing `readLines(stdin(), 1)`, _not_ `readLines(file("stdin"), 1)`. The semantics are slightly different, as noted in `?stdin`. – Mikael Jagan Mar 03 '22 at 06:04

1 Answers1

1

You can use blocking = FALSE. The following script will check input from stdin every half second and terminate when a full line is received.

#!/usr/bin/Rscript
inp <- file("stdin", "r", blocking = FALSE)
i <- 0
while (TRUE) {
    line <- readLines(inp, n = 1)
    if (length(line) > 0) {
        cat(sprintf("read a line: %s\n", line))
        break;
    }
    Sys.sleep(0.5)
    cat(sprintf("%d - nothing\n", i))
    i <- i + 1
}
Stefano Barbi
  • 2,978
  • 1
  • 12
  • 11
  • I think this is probably the best solution for right now. My only modifications is that I do a pushback in the first `if` statement before `break`. This way I can just use `readLines(input, -1L)` to get everything later. And also after the `Sys.sleep` call I put a timeout condition on `i`, so that it wont wait forever. – Justin Landis Mar 03 '22 at 16:15