如何在archive包的archive_extract完成目标文件提取后终止执行?
解决archive_extract()下载完目标文件后仍持续运行的问题
方法1:用curl仅下载归档中目标文件对应的字节段
archive_extract()默认会拉取整个远程归档,哪怕你只需要其中几个小文件。改用curl的范围请求特性,只下载目标文件对应的ZIP片段:
- 先获取远程归档里目标文件的位置和大小信息:
library(archive) # 替换成你的远程ZIP地址 zip_meta <- archive("https://your-archive-url/TIMSS2019_IDB_SPSS_G8.zip") # 筛选出目标.sav文件的元数据 target_meta <- zip_meta[grepl("TIMSS2019_IDB_SPSS_G8/Data/.*\\.sav", zip_meta$path), ] - 逐个下载目标文件对应的字节段并提取:
这种方式只会下载每个目标文件对应的ZIP部分,不会拉取整个1GB归档,也就不会有后续的无效等待。library(curl) dest_folder <- "./extracted_data" dir.create(dest_folder, recursive = TRUE, showWarnings = FALSE) for (i in seq(nrow(target_meta))) { file_info <- target_meta[i, ] # 构造字节范围:从起始位置到起始+文件大小-1 range_str <- paste0("bytes=", file_info$start, "-", file_info$start + file_info$size - 1) # 下载对应字节段到临时文件 temp_zip <- tempfile(fileext = ".zip") curl_download( url = "https://your-archive-url/TIMSS2019_IDB_SPSS_G8.zip", destfile = temp_zip, handle = new_handle(httpheader = list(Range = range_str)) ) # 从临时片段中提取目标文件 archive_extract(temp_zip, files = file_info$path, dir = dest_folder) unlink(temp_zip) }
方法2:用callr在子进程中执行提取,完成后强制终止
如果一定要直接用archive_extract(),可以把提取逻辑放到子进程里,检测到目标文件全部存在后杀掉子进程:
library(callr) library(fs) dest_folder <- "./extracted_data" # 替换成你要提取的两个.sav文件路径 target_files <- c( "TIMSS2019_IDB_SPSS_G8/Data/file1.sav", "TIMSS2019_IDB_SPSS_G8/Data/file2.sav" ) target_local_paths <- path(dest_folder, target_files) # 启动后台子进程执行提取 extract_proc <- r_bg(function(zip_url, dest_dir) { library(archive) archive_extract(zip_url, dir = dest_dir) }, args = list(zip_url = "https://your-archive-url/TIMSS2019_IDB_SPSS_G8.zip", dest_dir = dest_folder)) # 轮询检查目标文件是否全部生成 while(extract_proc$is_alive()) { if(all(file_exists(target_local_paths))) { extract_proc$kill() # 强制终止子进程 break } Sys.sleep(1) # 每秒检查一次 }
为什么stop()/break()没用?
因为archive_extract()是阻塞式的底层调用——它会先跑完整个归档的下载+提取流程,才会回到你的代码逻辑。你写的循环或stop判断都是在这个函数执行完之后才会触发,自然没法提前终止它。
内容的提问来源于stack exchange,提问作者panman
相关产品推荐
相关产品推荐

