R: >= 4GB 文件的可能截断

R: possible truncation of >= 4GB file

我有一个 370MB 的 zip 文件,内容是一个 4.2GB 的 csv 文件。

我做到了:

unzip("year2015.zip", exdir = "csv_folder")

我收到了这条消息:

1: In unzip("year2015.zip", exdir = "csv_folder") :
  possible truncation of >= 4GB file

你以前经历过吗?你是怎么解决的?

检查 ?unzip,在 Note 中发现以下评论:

It does have some support for bzip2 compression and > 2GB zip files (but not >= 4GB files pre-compression contained in a zip file: like many builds of unzip it may truncate these, in R's case with a warning if possible).

您可以尝试在 R 之外解压缩(例如使用 7-Zip)。

我同意@Sixiang.Hu的回答,R 的 unzip() 无法可靠地处理大于 4GB 的文件。

要了解 你是如何解决它的?:我尝试了一些不同的技巧,根据我的经验,使用 R 的内置函数的结果是(几乎)总是在文件的实际结尾之前错误地识别文件结尾 (EOF) 标记。

我在每晚处理的一组文件中处理这个问题,为了始终如一地以自动化方式处理它,我编写了下面的函数来 wrap UNIX 解压。 这基本上就是您使用 system(unzip()) 所做的,但在其行为上为您提供了更多的灵活性,并允许您更系统地检查错误。

decompress_file <- function(directory, file, .file_cache = FALSE) {

    if (.file_cache == TRUE) {
       print("decompression skipped")
    } else {

      # Set working directory for decompression
      # simplifies unzip directory location behavior
      wd <- getwd()
      setwd(directory)

      # Run decompression
      decompression <-
        system2("unzip",
                args = c("-o", # include override flag
                         file),
                stdout = TRUE)

      # uncomment to delete archive once decompressed
      # file.remove(file) 

      # Reset working directory
      setwd(wd); rm(wd)

      # Test for success criteria
      # change the search depending on 
      # your implementation
      if (grepl("Warning message", tail(decompression, 1))) {
        print(decompression)
      }
    }
}    

备注:

该函数做了一些我喜欢并推荐的事情:

  • 在系统上使用 system2 因为 the documentation 说 "system2 is a more portable and flexible interface than system"
  • 分隔directoryfile参数,并将工作目录移动到directory参数;根据您的系统,unzip(或您选择的解压缩工具)对于在工作目录外解压缩档案非常挑剔
    • 它并不纯粹,但重置工作目录是朝着副作用更少的功能迈出的重要一步
    • 从技术上讲,你可以在没有这个的情况下做到这一点,但根据我的经验,与必须处理生成文件路径和记住解压缩 CLI 标志相比,使函数更冗长更容易
  • 我将其设置为使用 -o 标志在重新运行时自动覆盖,但您可以提供任意数量的参数
  • 包含一个 .file_cache 参数,允许您跳过解压
    • 如果您正在测试在解压文件上运行的进程,这会派上用场,因为 4GB 以上的文件往往需要一些时间来解压
  • 在这个例子中被注释掉了,但是如果你知道你在解压后不需要这个档案,你可以直接删除它
  • system2命令将stdout重定向到解压,一个字符向量
    • an if + grepl 最后检查在标准输出中查找警告,如果发现表达式
    • 则打印标准输出

要添加到可能的解决方案列表中,如果您的计算机上有 Java (JDK),您可以将 jar xf 包装到类似于 utils::unzip()在界面中,一个很简单的例子:

unzipLarge <- function(zipfile, exdir = getwd()) {
  oldWd <- getwd()
  on.exit(setwd(oldWd))
  setwd(exdir)
  system2("jar", args = c("xf", zipfile))
}

然后使用:

unzipLarge("year2015.zip", exdir = "csv_folder")