是否有原因我无法直接从zip文件中读取RDS文件,而不必先将其解压缩到磁盘上的临时文件中?
假设这是zip文件:
saveRDS(cars, "cars.rds")
saveRDS(iris, "iris.rds")
write.csv(iris, "iris.csv")
zip("datasets.zip", c("cars.rds", "iris.rds", "iris.csv"))
file.remove("cars.rds", "iris.rds", "iris.csv")
对于csv文件,我可以像这样直接读取它:
iris2 <- read.csv(unz("datasets.zip", "iris.csv"))
但是,我不明白为什么我不能直接将
unz()
与readRDS()
一起使用:iris3 <- readRDS(unz("datasets.zip", "iris.rds"))
这给了我错误:
Error: unknown input format
我也想了解为什么会这样。我知道我可以执行以下操作,例如this question:
path <- unzip("datasets.zip", "iris.rds")
iris4 <- readRDS(path)
file.remove(path)
但是,这似乎不太有效,我需要经常处理大量文件,因此I/O效率低下很重要。是否有任何解决方法来读取rds文件而不将其提取到磁盘中?
最佳答案
在我阅读readRDS()
的正文之前,要跟踪它有点棘手。看来您需要做的是
.zip
打开到unz()
存档及其内部文件的连接gzcon()
readRDS()
。 这是一个示例,用于说明在zip存档
mat
中使用以下序列化矩阵matrix.zip
mat <- matrix(1:9, ncol = 3)
saveRDS(mat, "matrix.rds")
zip("matrix.zip", "matrix.rds")
打开与
matrix.zip
的连接con <- unz("matrix.zip", filename = "matrix.rds")
现在,使用
gzcon()
将GZIP解压缩应用于此连接con2 <- gzcon(con)
最后,从连接中读取
mat2 <- readRDS(con2)
总的来说,我们有
con <- unz("matrix.zip", filename = "matrix.rds")
con2 <- gzcon(con)
mat2 <- readRDS(con2)
close(con2)
这给
> con <- unz("matrix.zip", filename = "matrix.rds")
> con2 <- gzcon(con)
> mat2 <- readRDS(con2)
> close(con2)
> mat2
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> all.equal(mat, mat2)
[1] TRUE
为什么?
我必须在
?readRDS
中描述为什么要经历这个复杂的额外步骤:如果您查看
readRDS()
的内部信息,我们会看到:> readRDS
function (file, refhook = NULL)
{
if (is.character(file)) {
con <- gzfile(file, "rb")
on.exit(close(con))
}
else if (inherits(file, "connection"))
con <- file
else stop("bad 'file' argument")
.Internal(unserializeFromConn(con, refhook))
}
<bytecode: 0x2841998>
<environment: namespace:base>
如果
file
是文件名的字符串,则使用gzile()
对对象进行解压缩以创建与我们要读取的.rds
的连接。请注意,如果您按需通过file
传递连接,则R绝对不会解压缩该连接。只是将file
分配给con
,然后将其传递给内部函数unserializeFromConn
。因此,将gzcon()
包裹在unz
创建的连接周围即可。基本上,当
unserializeFromConn
从连接中读取时,它希望将其解压缩,但是只有当您将readRDS()
传递给文件名而不是连接时,解压缩才会自动发生。关于r - 在不解压缩到磁盘的情况下读取zip文件中的RDS文件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33289973/