Home > Software engineering >  Make reading RDS from stdin independent whether the file was created via pipe or not
Make reading RDS from stdin independent whether the file was created via pipe or not

Time:03-04

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?

CodePudding user response:

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.

  •  Tags:  
  • r
  • Related