有没有理由我无法直接从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")
Run Code Online (Sandbox Code Playgroud)
对于csv文件,我可以直接读取它:
iris2 <- read.csv(unz("datasets.zip", "iris.csv"))
Run Code Online (Sandbox Code Playgroud)
但是,我不明白为什么我不能unz()直接使用readRDS():
iris3 <- readRDS(unz("datasets.zip", "iris.rds"))
Run Code Online (Sandbox Code Playgroud)
这给了我错误:
Error: unknown input format
Run Code Online (Sandbox Code Playgroud)
我也想知道为什么会这样.我知道我可以做以下事情,就像这个问题一样:
path <- unzip("datasets.zip", "iris.rds")
iris4 <- readRDS(path)
file.remove(path)
Run Code Online (Sandbox Code Playgroud)
但这似乎并不高效,而且我需要经常为大量文件执行此操作,因此I/O效率低下很重要.是否有任何解决方法来读取rds文件而不将其提取到磁盘?
这是一个有点棘手的追踪,直到我读到的身体readRDS().你需要做的是
.zip存档及其中文件的连接unz()gzcon()readRDS().下面是一个示例,用于说明mat在zip存档中使用以下序列化矩阵matrix.zip
mat <- matrix(1:9, ncol = 3)
saveRDS(mat, "matrix.rds")
zip("matrix.zip", "matrix.rds")
Run Code Online (Sandbox Code Playgroud)
打开连接 matrix.zip
con <- unz("matrix.zip", filename = "matrix.rds")
Run Code Online (Sandbox Code Playgroud)
现在,使用gzcon(),将GZIP解压缩应用于此连接
con2 <- gzcon(con)
Run Code Online (Sandbox Code Playgroud)
最后,从连接中读取
mat2 <- readRDS(con2)
Run Code Online (Sandbox Code Playgroud)
完全我们有
con <- unz("matrix.zip", filename = "matrix.rds")
con2 <- gzcon(con)
mat2 <- readRDS(con2)
close(con2)
Run Code Online (Sandbox Code Playgroud)
这给了
> 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
Run Code Online (Sandbox Code Playgroud)
为什么你必须经历这个复杂的额外步骤(我认为)描述于?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>
Run Code Online (Sandbox Code Playgroud)
如果file是文件名的字符串,则使用该对象解压缩gzile()以创建与.rds我们要读取的连接.请注意,如果您file按照自己的意愿传递连接,则R在任何时候都不会解压缩连接.file只是分配给con然后传递给内部函数unserializeFromConn.因此缠绕工作gzcon()创建的连接unz.
基本上,当unserializeFromConn从连接读取时,它期望它被解压缩,但是当您传递readRDS()文件名而不是连接时,解压缩只会自动发生.
| 归档时间: |
|
| 查看次数: |
2223 次 |
| 最近记录: |