使用archive_write_dir()导致栅格文件损坏的问题排查
法国气象局提供的降水再分析数据以.tar归档形式发布,每个归档包含三种栅格文件:降水总量、估算误差和雷达状态。我只需要保留带_RR.gtif后缀的降水栅格,但重新打包后提取的文件无法用terra导入,报错信息如下:
Error: [rast] cannot open this file as a SpatRaster: [...]/temp/2022/2022010101_RR.gtif
警告信息:
1: [...]/temp/2022/2022010101_RR.gtif:Failed to allocate memory for to read TIFF directory (0 elements of 12 bytes each) (GDAL error 1)
2: [...]temp/2022/2022010101_RR.gtif: TIFFReadDirectory:Failed to read directory at offset 18782 (GDAL error 1)
我的R脚本如下:
library(archive) library(terra) # download an example archive download.file(url="https://object.files.data.gouv.fr/meteofrance/data/synchro_ftp/REANALYSES/COMEPHORE/H_COMEPHORE_202201.tar", destfile = "H_COMEPHORE_202201.tar", mode = "wb") # list and filter the files inside the archive dat.files<-unlist(archive("H_COMEPHORE_202201.tar")) dat.files<-grep(pattern="_RR.gtif", x = dat.files, value = TRUE) # extract those files into a folder archive_extract("H_COMEPHORE_202201.tar", files = dat.files, dir="temp") # import one of the rasters using terra RR<-rast("temp/2022/2022010101_RR.gtif") plot(RR) # this works fine # write the precipitation files into a new archive archive_write_dir(archive = "archive.tar", dir = "temp", recursive = TRUE) # clear the folder unlink("temp/*", recursive = TRUE) # extract the files again archive_extract("archive.tar", dir="temp") # import the same raster again using terra RR<-rast("temp/2022/2022010101_RR.gtif") # does not work anymore
原因与解决方法
问题根源
archive_write_dir()函数在处理二进制文件(比如GTIF栅格)时,可能因默认的文件写入逻辑导致文件损坏。GTIF是二进制格式,对文件完整性要求极高,一旦打包过程中出现编码或模式错误,就会导致GDAL无法读取TIFF目录。
解决方案:改用基础R的tar()函数打包
基础R的tar()函数对二进制文件的兼容性更好,能确保文件原封不动被打包。修改后的脚本如下:
library(archive) library(terra) # 下载示例归档 download.file(url="https://object.files.data.gouv.fr/meteofrance/data/synchro_ftp/REANALYSES/COMEPHORE/H_COMEPHORE_202201.tar", destfile = "H_COMEPHORE_202201.tar", mode = "wb") # 列出并筛选归档内的文件 dat.files <- unlist(archive("H_COMEPHORE_202201.tar")) dat.files <- grep(pattern="_RR.gtif", x = dat.files, value = TRUE) # 提取文件到临时文件夹 archive_extract("H_COMEPHORE_202201.tar", files = dat.files, dir="temp") # 测试导入正常 RR <- rast("temp/2022/2022010101_RR.gtif") plot(RR) # 改用基础R的tar函数打包,禁用压缩避免损坏二进制文件 tar("archive.tar", files = list.files("temp", recursive = TRUE, full.names = TRUE), compression = "none") # 清空临时文件夹 unlink("temp/*", recursive = TRUE) # 重新提取文件 archive_extract("archive.tar", dir="temp") # 再次导入测试 RR <- rast("temp/2022/2022010101_RR.gtif") plot(RR) # 现在可以正常读取
备选方案:使用archive_write_files()精准指定文件
如果坚持使用archive包,可改用archive_write_files()直接指定要打包的文件,而非整个目录,避免目录处理带来的问题:
# 替代archive_write_dir的写法 files_to_archive <- list.files("temp", recursive = TRUE, full.names = TRUE) archive_write_files("archive.tar", files_to_archive)
内容的提问来源于stack exchange,提问作者ucfaard

