R如何直接读取S3返回的压缩CSV原始向量到内存无需临时文件
问题描述
我有一份存放在S3存储桶中的gzip压缩CSV格式数据集,通过S3 API拉取后返回的是原始向量格式。我现在的处理流程是先把这个原始向量写入本地临时文件,再从文件读取数据。
请问有没有办法直接从原始向量读取数据,不需要写入临时文件?
当前代码
# Import packages ------------------------------------------------------------- library(paws) # Set up S3 access ------------------------------------------------------------ s3 <- paws::s3() aws_s3_bucket <- Sys.getenv("AWS_S3_BUCKET") # Fetch dataset from S3 which returns a raw vector ---------------------------- s3_object <- s3$get_object(Bucket = aws_s3_bucket, Key = "data.csv.gz") s3_object_body <- s3_object$Body # Write the raw vector to a temporary file (This is what I want to remove) ---- file_name <- "s3_files/mydataset.csv.gz" if (file.exists(file_name)) { unlink(file_name) } writeBin(s3_object_body, con = file_name) # Finally, read the data from the file ---------------------------------------- data <- data.table::fread(file_name)
已尝试未成功的方案
- 尝试使用
readr::read_csv(s3_object_body)读取,报错如下:
Error in vroom_(file, delim = delim %||% col_types$delim, col_names = col_names, : embedded nul in string: '\037<U+008B>\b\b<f1>7\aa\002<ff>data.csv'
- 尝试使用
iotools::read.csv.raw(s3_object_body)读取,报错如下:
Error in isOpen(con, "rb") : unimplemented type 'raw' in 'asInteger'
解决方案
之前尝试失败的原因是拿到的s3_object_body是gzip压缩后的二进制原始向量,没有先做解压缩就直接传入读取函数,所以会识别到二进制空字符报错。
不需要写入本地文件的实现逻辑是:先把原始向量封装为内存连接,再套上gzip解压缩连接,直接传入读取函数即可。两种常用的实现方式如下:
方式1:配合data.table::fread使用(和现有读取习惯一致)
# 拿到S3返回的原始向量后直接处理,无需写本地文件 s3_object <- s3$get_object(Bucket = aws_s3_bucket, Key = "data.csv.gz") s3_object_body <- s3_object$Body # 创建内存原始连接,套gzip解压缩连接 raw_conn <- gzcon(rawConnection(s3_object_body)) # 直接读取数据 data <- data.table::fread(raw_conn) # 用完关闭连接 close(raw_conn)
方式2:配合readr::read_csv使用
library(readr) s3_object <- s3$get_object(Bucket = aws_s3_bucket, Key = "data.csv.gz") s3_object_body <- s3_object$Body raw_conn <- gzcon(rawConnection(s3_object_body)) data <- read_csv(raw_conn, show_col_types = FALSE) close(raw_conn)
内容的提问来源于stack exchange,提问作者Chris Nemarich
相关产品推荐
相关产品推荐

