最近做的项目,需要从用户手里拿到一个 R 对象文件,姑且叫 out.rdata,后台要从这个 out.rdata 中取出一个叫 fuck 的对象。原来一直是用load('out.rdata')这种方式加载,没发现问题,直到昨天发现一个报错的记录:

Error in load('out.rdata') :
  bad restore file magic number (file may be corrupted) -- no data loaded
In addition: Warning message:
file ‘seurat.rdata’ has magic number 'X'
  Use of save versions prior to 2 is deprecated
Execution halted

放狗一搜,发现这篇文章:

https://yihui.name/en/2017/12/save-vs-saverds/

猜测可能用户是用saveRDS()方法保存的数据,于是对应的,用readRDS()加载就正常了。

但谁知道用户爸爸哪天心情好又换save()存咋办?

所以需要做个判断:如果是save()保存的数据,用load();如果是saveRDS()保存的,则用readRDS()

那么问题来了,怎么判断*.rdata的保存方式方法?

继续放狗,未果

换思路,Try…Catch 之:先load()扑街了再用readRDS(),代码如下:

R 的tryCatch写起来好丑陋。。。

library(stringr)

loadFuck <- function(fp) {
  out <- tryCatch({
    # 大佬建议用 attach
    attach(fp)$fuck
  }, warning = function(e) {
    # 这里扑街提示是 warning
    return(readRDS(fp))
  }, error = function(e) {
    # 真扑街那没办法,停车报警
    stop('cannot load R object')
  }, finally = {
    # attach 完了打扫现场
    name = paste("file", fp, sep = ":")
    detach(name, character.only = TRUE)
  })
  return(out)
}

fuck <- loadFuck('out.rdata')

搞定!

贴个参考文章的好评论

Great post! If you really want to use save() and then want load it back, use attach() instead of load(). The former will warn you about overwriting. Also you can unload it with detach("file:foo.RData").