如何使用R读取zip压缩文件中打包文件的大小
问题描述:
R中的以下代码返回一个数据帧,其中包含文件名,解包长度(以字节为单位)和日期(不提取文件)。如何使用R读取zip压缩文件中打包文件的大小
unzip(path_to_zip, list = T)
我想知道如何也可以提取打包(压缩)文件的大小,或者每个文件的压缩比。
我正在使用Windows 7机器。
谢谢!
答
使用unzip()
函数,您不能:默认情况下,它使用内部C函数来完成它的功能,仅此而已。但是,它可以使用外部可执行文件,并且确实允许允许详细信息(使用-v
)。为了使用它,你需要修改R的unzip()
函数。这个答案的其余部分是练习“使用源,卢克”,表明当前的功能可以在需要时扩展。
unzip2 <- function (zipfile, files = NULL, list = FALSE, list.verbose = FALSE, overwrite = TRUE,
junkpaths = FALSE, exdir = ".", unzip = "internal", setTimes = FALSE) {
if (identical(unzip, "internal")) {
if (!list && !missing(exdir))
dir.create(exdir, showWarnings = FALSE, recursive = TRUE)
res <- .External(utils:::C_unzip, zipfile, files, exdir, list,
overwrite, junkpaths, setTimes)
if (list) {
dates <- as.POSIXct(res[[3]], "%Y-%m-%d %H:%M", tz = "UTC")
data.frame(Name = res[[1]], Length = res[[2]], Date = dates,
stringsAsFactors = FALSE)
}
else invisible(attr(res, "extracted"))
}
else {
WINDOWS <- .Platform$OS.type == "windows"
if (!is.character(unzip) || length(unzip) != 1L || !nzchar(unzip))
stop("'unzip' must be a single character string")
zipfile <- path.expand(zipfile)
if (list) {
dashl <- if (list.verbose) "-lv" else "-l"
res <- if (WINDOWS)
system2(unzip, c(dashl, shQuote(zipfile)), stdout = TRUE)
else system2(unzip, c(dashl, shQuote(zipfile)), stdout = TRUE,
env = c("TZ=UTC"))
l <- length(res)
res2 <- res[-c(1, 3, l - 1, l)]
con <- textConnection(res2)
on.exit(close(con))
z <- read.table(con, header = TRUE, as.is = TRUE)
dt <- paste(z$Date, z$Time)
formats <- if (max(nchar(z$Date) > 8))
c("%Y-%m-%d", "%d-%m-%Y", "%m-%d-%Y")
else c("%m-%d-%y", "%d-%m-%y", "%y-%m-%d")
slash <- any(grepl("/", z$Date))
if (slash)
formats <- gsub("-", "/", formats)
formats <- paste(formats, "%H:%M")
for (f in formats) {
zz <- as.POSIXct(dt, tz = "UTC", format = f)
if (all(!is.na(zz)))
break
}
z[, "Date"] <- zz
z <- z[, colnames(z) != "Time"]
nms <- c("Name", "Length", "Date")
z[, c(nms, setdiff(colnames(z), nms))]
}
else {
args <- c("-oq", shQuote(zipfile))
if (length(files))
args <- c(args, shQuote(files))
if (exdir != ".")
args <- c(args, "-d", shQuote(exdir))
system2(unzip, args, stdout = NULL, stderr = NULL,
invisible = TRUE)
invisible(NULL)
}
}
}
在此,我修改线:1(参数),6(utils:::
),21-25(dashl
),45和46-47中加入(列选择)。其余的是从原来的R unzip
功能。
默认情况下,unzip2
的行为与unzip
完全相同,这意味着它不会给你想要的东西。为了得到您想要的结果,您需要(a)告诉它您的外部unzip.exe
位于何处,并且(b)告诉它您希望它是冗长的。 (请随意修改上述定义以更改默认值。)
请注意,在Windows上,unzip.exe
默认情况下通常不会安装。它包含在Rtools,Git-for-Windows和msys2中。您可能需要更多努力才能确保Sys.which("unzip")
找到可执行文件。
这使用(默认)内部C函数,这意味着没有更多可以来。
unzip2("~/bashdotfiles.zip", list = TRUE)
# Name Length Date
# 1 .bash_history 8269 2017-02-20 03:31:00
# 2 .bash_logout 220 2016-04-22 22:36:00
# 3 .bashrc 3771 2016-04-22 22:36:00
它们使用外部可执行文件,并且在功能上是相同的(虽然注意到日期,由于内部UTC转换是不同的......这可能是固定一点点更多的努力)。
unzip2("~/bashdotfiles.zip", list = TRUE, unzip = Sys.which("unzip"))
# Name Length Date
# 1 .bash_history 8269 2017-02-20 11:31:00
# 2 .bash_logout 220 2016-04-23 05:36:00
# 3 .bashrc 3771 2016-04-23 05:36:00
最后,增强上市:
unzip2("~/bashdotfiles.zip", list = TRUE, list.verbose = TRUE, unzip = Sys.which("unzip"))
# Name Length Date Method Size Cmpr CRC.32
# 1 .bash_history 8269 2017-02-20 11:31:00 Defl:N 2717 67% 99c8d736
# 2 .bash_logout 220 2016-04-23 05:36:00 Defl:N 158 28% 6ce3189b
# 3 .bashrc 3771 2016-04-23 05:36:00 Defl:N 1740 54% ab254644
非常感谢详细的解答!但是,代码中似乎存在某种错误。如果zip文件中的一个文件的文件名中有空格,则代码将崩溃。例如,我试图在一个zip文件上运行一个代码,其中包含一个名为“a b.pdf”的文件。该代码返回以下值:502521,b.PDF,Defl:N,,448514,11%,2016-05-18,a'。如果文件名超过1个空格,则代码崩溃。 –
Sasha
这是否发生在'utils :: unzip()'? – r2evans
无论何时使用外部解压缩可执行文件,这都是'unzip'中的一个错误。这个'unzip2'忠实地复制了这种行为:-)。 – r2evans