我想出了以下解决方案,适用于小于2^32-1字节的文件大小。
R对象需要进行序列化并保存到文件中,可以使用以下代码来实现。
saveObj <- function(object, file.name){
outfile <- file(file.name, "wb")
serialize(object, outfile)
close(outfile)
}
然后我们分块读取二进制数据,记录已经读取了多少并相应地更新进度条。
loadObj <- function(file.name){
library(foreach)
filesize <- file.info(file.name)$size
chunksize <- ceiling(filesize / 100)
pb <- txtProgressBar(min = 0, max = 100, style=3)
infile <- file(file.name, "rb")
data <- foreach(it = icount(100), .combine = c) %do% {
setTxtProgressBar(pb, it)
readBin(infile, "raw", chunksize)
}
close(infile)
close(pb)
return(unserialize(data))
}
这段代码可以按以下方式运行:
> a <- 1:100000000
> saveObj(a, "temp.RData")
> b <- loadObj("temp.RData")
|======================================================================| 100%
> all.equal(b, a)
[1] TRUE
如果我们将进度条方法与一次读取整个文件相比较,我们会发现进度条方法稍微慢了一些,但这并不值得担心。
> system.time(unserialize(readBin(infile, "raw", file.info("temp.RData")$size)))
user system elapsed
2.710 0.340 3.062
> system.time(b <- loadObj("temp.RData"))
|======================================================================| 100%
user system elapsed
3.750 0.400 4.154
虽然上述方法是可行的,但由于文件大小限制,我认为它是完全无用的。进度条只对需要长时间读取的大文件有用。
如果有人能提出比这个解决方案更好的方法,那就太好了!
x <- matrix(runif(1e7), 1e5) # Matrix with 100k rows and 100 columns
system.time( save('x', file='c:/foo.bin') ) # 13.26 seconds
system.time( load(file='c:/foo.bin') ) # 2.03 seconds
system.time( save('x', file='c:/foo.bin', compress=FALSE) ) # 0.86 seconds
system.time( load(file='c:/foo.bin') ) # 0.92 seconds
system.time( saveMatrix(x, 'c:/foo.bin') ) # 0.70 seconds
system.time( y <- loadMatrix('c:/foo.bin') ) # 0.11 seconds !!!
identical(x,y)
saveMatrix/loadMatrix的定义如下。它们目前不处理dimnames和其他属性,但这很容易添加。
saveMatrix <- function(m, fileName) {
con <- file(fileName, 'wb')
on.exit(close(con))
writeBin(dim(m), con)
writeBin(typeof(m), con)
writeBin(c(m), con)
}
loadMatrix <- function(fileName) {
con <- file(fileName, 'rb')
on.exit(close(con))
d <- readBin(con, 'integer', 2)
type <- readBin(con, 'character', 1)
structure(readBin(con, type, prod(d)), dim=d)
}
txtProgressBar
和gtkProgressBar
。后者是来自 RGtk2 包。这些是否符合您的需求? - jthetzeltxtProgressBar
函数了,而且您的问题实际上是关于加载 .Rdata 文件的。 - jthetzel