user1424739
user1424739

Reputation: 13775

Make reading RDS from stdin independent whether the file was created via pipe or not

readRDS=function(file = pipe('cat', 'rb'), ...) {
    base::readRDS(file, ...)
}
saveRDS=function(object, file = pipe('cat', 'wb'), ...) {
    base::saveRDS(object, file, ...)
}

I use the above function to read an RDS file from stdin and write an RDS file to stdout.

See below, one readRDS call works, the other doesn't. It depends on whether the rds file is written using pipe or not.

$ lr -e 'source("saveRDS.R"); saveRDS(1:3, file="/tmp/readRDS.rds");'
$ lr -e 'source("readRDS.R"); print(readRDS());' < /tmp/readRDS.rds
Error in base::readRDS(file, ...) : unknown input format
$ lr -e 'source("saveRDS.R"); saveRDS(1:3);' > /tmp/readRDS.rds
$ lr -e 'source("readRDS.R"); print(readRDS());' < /tmp/readRDS.rds
[1] 1 2 3

Why does it depend on the way the file is written? Is there a way to make readRDS from stdin always work whether the file is written via pipe or not?

Upvotes: 1

Views: 70

Answers (1)

MrFlick
MrFlick

Reputation: 206566

There seems to be a difference between compression between the two methods. Rather than reading from cat in the readRDS Try

readRDS=function(file = base::gzcon(base::file("stdin", "rb")), ...) {
    base::readRDS(file, ...)
}

The gzcon will do the compression if the gz magic number is found, otherwise it will just pass through the file normally. This should allow things to work in both cases.

Upvotes: 2

Related Questions