data.table::fwrite生成的gzip文件异常:Ubuntu管理器无法解压
使用data.table::fwrite生成的gzip文件无法被Ubuntu文件管理器正常解压的问题
问题现象
用data.table::fwrite(dt, 'teste.csv.gz')将data.table保存为gzip压缩文件后:
- Ubuntu文件管理器解压时提示“空归档错误”,无法正常处理
- 命令行执行
gunzip -l teste.csv.gz返回异常的负压缩率(示例中为-1129.1%) - 但命令行
gunzip teste.csv.gz可以正常解压文件 - 若先导出未压缩CSV,再用系统
gzip命令压缩,生成的文件既可以被Ubuntu文件管理器正常解压,gunzip -l也会显示正常的压缩率(示例中为55.8%)
重现代码
library(data.table) # 创建测试数据 dt <- data.table(a = 1:100000, b = runif(100000)) # 用fwrite直接生成gzip文件 fwrite(dt, 'teste.csv.gz') # 查看压缩信息,显示异常比率 res <- system('gunzip -l teste.csv.gz', intern = TRUE) res #> [1] " compressed uncompressed ratio uncompressed_name" #> [2] " 1055898 85906 -1129.1% teste.csv" # 命令行可正常解压 system('gunzip teste.csv.gz') # 用系统gzip命令压缩,生成正常文件 system('gzip teste.csv') res <- system('gunzip -l teste.csv.gz', intern = TRUE) res #> [1] " compressed uncompressed ratio uncompressed_name" #> [2] " 1054997 2388946 55.8% teste.csv" sessionInfo() #> R version 4.4.0 (2024-04-24) #> Platform: x86_64-pc-linux-gnu #> Running under: Ubuntu 20.04.6 LTS #> #> Matrix products: default #> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 #> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/liblapack.so.3; LAPACK version 3.9.0 #> #> locale: #> [1] LC_CTYPE=pt_BR.UTF-8 LC_NUMERIC=C #> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 #> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=C #> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C #> [9] LC_ADDRESS=C LC_TELEPHONE=C #> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C #> #> time zone: America/Sao_Paulo #> tzcode source: system (glibc) #> #> attached base packages: #> [1] stats graphics grDevices utils datasets methods base #> #> other attached packages: #> [1] data.table_1.15.4 #> #> loaded via a namespace (and not attached): #> [1] styler_1.10.3 digest_0.6.35 fastmap_1.2.0 xfun_0.44 #> [5] magrittr_2.0.3 glue_1.7.0 R.utils_2.12.3 knitr_1.47 #> [9] htmltools_0.5.8.1 rmarkdown_2.27 lifecycle_1.0.4 cli_3.6.2 #> [13] R.methodsS3_1.8.2 vctrs_0.6.5 reprex_2.1.0 withr_3.0.0 #> [17] compiler_4.4.0 R.oo_1.26.0 R.cache_0.16.0 purrr_1.0.2 #> [21] rstudioapi_0.16.0 tools_4.4.0 evaluate_0.23 yaml_2.3.8 #> [25] rlang_1.1.3 fs_1.6.4
原因分析
这不是data.table::fwrite的bug,而是其gzip压缩实现与系统gzip的差异:
fwrite直接将数据压缩为gzip流写入文件,但未在gzip头部写入原始未压缩文件大小的元数据- Ubuntu文件管理器和
gunzip -l依赖这个元数据来识别归档内容、计算压缩率,因此出现错误提示和异常比率 gunzip命令本身不依赖该元数据,可直接解压缩流,所以能正常解压
解决办法
方法1:先导出未压缩CSV,再用系统gzip压缩
fwrite(dt, 'teste.csv') system('gzip teste.csv')
生成的文件完全兼容系统工具和文件管理器。
方法2:使用fwrite的compress参数(需data.table新版本)
升级到最新版data.table后,显式指定compress = "gzip"参数,生成的文件会包含完整的gzip元数据:
fwrite(dt, 'teste.csv.gz', compress = "gzip")
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

