You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言内存不足时如何分块遍历读取多个大型CSV文件

问题原因
  • 原代码对每个文件仅执行1次read.csv读取1000行,未添加单个文件内的分块遍历逻辑,因此只能拿到每个文件的前1000行数据
  • 连接关闭操作写在循环外部,仅能关闭最后一个文件的连接,会造成前面文件的连接资源泄漏
  • 直接将所有分块存入file_contents列表的逻辑会最终把所有文件数据加载到内存,不符合分块读取节省内存的设计初衷,常规分块方案建议读完一个分块就执行对应计算逻辑,无需保留全量分块数据
修正后实现代码

场景1:逐块处理无需保留全量数据(推荐,内存占用最低)

library(tidyverse)
library(fs)

file_paths <- fs::dir_ls("path/to/folder")
chunkSize <- 1000

for(i in seq_along(file_paths)){
  current_path <- file_paths[[i]]
  con <- file(current_path, "r")
  # 预读表头,避免每次读取分块重复处理表头
  header <- readLines(con, n = 1)
  col_names <- unlist(strsplit(header, ","))
  
  # 循环遍历当前文件的所有分块
  while(TRUE){
    chunk <- read.csv(con, nrows = chunkSize, header = FALSE, col.names = col_names)
    # 分块读取完毕时跳出循环
    if(nrow(chunk) == 0) break
    
    # 此处写入你对当前分块的处理逻辑,例如统计、过滤、写入结果文件等
    # 示例:打印当前分块的行数和所属文件
    message("当前文件: ", current_path, " 分块行数: ", nrow(chunk))
  }
  
  close(con)
}

场景2:确实需要存储所有分块(需确认内存足够容纳全量数据)

library(tidyverse)
library(fs)

file_paths <- fs::dir_ls("path/to/folder")
file_contents <- list()
chunkSize <- 1000
chunk_idx <- 1

for(i in seq_along(file_paths)){
  current_path <- file_paths[[i]]
  con <- file(current_path, "r")
  header <- readLines(con, n = 1)
  col_names <- unlist(strsplit(header, ","))
  
  while(TRUE){
    chunk <- read.csv(con, nrows = chunkSize, header = FALSE, col.names = col_names)
    if(nrow(chunk) == 0) break
    
    file_contents[[chunk_idx]] <- chunk
    # 给分块命名,格式为 文件路径_分块序号
    names(file_contents)[chunk_idx] <- paste0(current_path, "_chunk_", chunk_idx)
    chunk_idx <- chunk_idx + 1
  }
  
  close(con)
}
更简便的替代方案:使用readr包的分块读取函数

readr内置的read_csv_chunked可以省去手动管理连接的逻辑,代码更简洁:

library(tidyverse)
library(fs)

file_paths <- fs::dir_ls("path/to/folder")
chunkSize <- 1000

# 定义分块处理函数
process_chunk <- function(chunk, pos){
  # 此处写入分块处理逻辑,pos为当前分块的序号
  message("当前分块序号: ", pos, " 分块行数: ", nrow(chunk))
}

# 遍历所有文件执行分块处理
walk(file_paths, ~ read_csv_chunked(.x, 
                                    callback = SideEffectChunkCallback$new(process_chunk),
                                    chunk_size = chunkSize))

内容的提问来源于stack exchange,提问作者Hanne Utheim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 03:06:03