如何使用 R 读取 zip 存档中打包文件的大小

How to read sizes of packed files inside zip archive using R

R returns 中的以下代码是一个数据框,其中包括文件名、以字节为单位的解压缩长度和日期(不提取文件)。

unzip(path_to_zip, list  = T)

我想知道如何提取打包(压缩)文件的大小或每个文件的压缩率。

我正在使用Windows 7 机器。

谢谢!

使用 unzip() 函数,你不能:默认情况下,它使用一个内部 C 函数来完成它所做的,仅此而已。但是,它可以使用外部可执行文件,并且 确实 允许详细信息(-v)。为了使用它,您需要修改 R 的 unzip() 函数。这个答案的其余部分是 "use the source, luke" 的练习,表明可以在需要时扩展当前功能。

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, and 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