这有点棘手,直到我阅读了
readRDS()
的正文之后才找到了解决方法。它似乎需要你执行以下操作:
- 使用
unz()
打开.zip
存档和其中的文件。
- 使用
gzcon()
对此连接应用GZIP解压缩。
- 最后将此已解压缩的连接传递给
readRDS()
。
这里有一个示例,演示如何在
matrix.zip
压缩档案中使用以下序列化矩阵
mat
。
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
中(我认为)有描述:
当file
是一个文件名时,压缩是由打开的连接处理的,因此仅当file
是一个连接时才可能由连接处理。 因此,例如url
连接将需要在调用gzcon
中包装。
如果您查看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
。因此,在由
unz
创建的连接周围包装
gzcon()
有效。
基本上,当
unserializeFromConn
从连接中读取数据时,它期望该连接已被解压缩,但仅当您传递一个文件名而不是连接时,才会自动进行解压缩。
iris3 <- readRDS(gzcon(unz("datasets.zip", "iris.rds")))
。 - cocquemas