integer64值存入RDS文件后读取异常的原因及相关疑问
bit64::integer64类型在saveRDS/readRDS中的异常问题解答
问题概述
- 使用
data.table::fread读取包含超大整数的.dat文件时,目标列(如TUCASEID)的类型为bit64::integer64 - 调用
saveRDS保存该列后,同一会话内用readRDS读取数值正常,但新会话读取时,数值出现异常(例如原数值20030100013007变为9.896184e-311),且数据类型变为普通integer(上限为2^31)
原因分析
- 这不是bug,属于序列化/反序列化的依赖包依赖问题:
bit64::integer64是自定义数据类型,其序列化(saveRDS)会记录类型元信息,但反序列化(readRDS)时需要bit64包的支持才能正确解析二进制数据- 新会话未加载
bit64(或依赖它的data.table)时,readRDS无法识别该自定义类型,会将底层二进制流错误解析为普通浮点数(即出现的异常小数值),而非原本的integer64类型
- 同会话与新会话的差异原因:
- 同会话中已经加载了
bit64包,readRDS时能匹配到对应的类型解析逻辑,因此数值正常 - 新会话未加载依赖包,只能用默认的基础类型解析规则,导致类型和数值异常
- 同会话中已经加载了
- 不存在缓存机制,完全由包加载状态决定解析结果
解决方案
方案1:读取前加载依赖包
在新会话读取RDS文件前,先加载bit64或data.table包:
library(bit64) # 或 library(data.table) data <- readRDS("data.RDS")
方案2:保存前转换为字符型
如果不需要后续数值运算,可将integer64类型转换为字符型后再保存,彻底避免类型解析问题:
library(data.table) data <- data.table::fread("atuscps_0321.dat") data[, TUCASEID := as.character(TUCASEID)] saveRDS(data[, "TUCASEID"], file="data.RDS")
内容的提问来源于stack exchange,提问作者Axel
相关产品推荐
相关产品推荐

