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

Ruby导入CSV报Unquoted fields do not allow \r or \n错误如何解决

CSV导入Oracle报错解决方案

报错根因

你遇到的CSV::MalformedCSVError: Unquoted fields do not allow \r or \n (line 1)报错本质原因有两个:

  • 预处理阶段没有完全清除换行符格式差异,Windows导出的CSV常带BOM头或混合换行符,触发CSV解析器的严格校验
  • 行尾带逗号的非标格式,和Ruby默认CSV解析的严格规则不兼容

修正后的预处理代码

def csv_replace_empty_string
  Dir.foreach(Rails.root.join('db', 'csv_export')) do |filename|
    next if ['.', '..', 'extract_db_into_csv.sh', 'import_csv.rb'].include?(filename)
    file_path = Rails.root.join('db', 'csv_export', filename)
    # 二进制读取避免编码兼容问题
    content = File.read(file_path, mode: 'rb')
    # 统一所有换行符为\n
    content.gsub!(/\r\n?/, "\n")
    # 清除UTF-8 BOM头,解决首行解析报错问题
    content.gsub!(/\A\xEF\xBB\xBF/, '')
    # 替换空双引号为带空格的引号,避免空值解析异常
    content.gsub!(/(?<=,|^)""(?=,|$)/, '" "')
    # 统一行尾结构,对齐表头字段数量
    header_field_count = content.lines.first.split(',').count
    content = content.lines.map do |line|
      stripped_line = line.strip
      next if stripped_line.empty?
      # 去除行尾多余逗号
      normalized_line = stripped_line.chomp(',')
      # 补全字段数量和表头一致,避免字段数量不匹配报错
      fields = normalized_line.split(',', header_field_count)
      (fields + [''] * (header_field_count - fields.size)).join(',')
    end.compact.join("\n") + "\n"
    File.write(file_path, content)
  end
end

修正后的导入代码

核心是开启liberal_parsing宽松解析参数,适配非标CSV格式:

def import_csv_into_db
  Dir.foreach(Rails.root.join('db', 'csv_export')) do |filename|
    next if ['.', '..', 'extract_db_into_csv.sh', 'import_csv.rb'].include?(filename)
    file_path = Rails.root.join('db', 'csv_export', filename)
    model_class = File.basename(filename, File.extname(filename)).classify.constantize
    CSV.foreach(
      file_path,
      headers: true,
      skip_blanks: true,
      row_sep: "\n",
      quote_char: '"',
      liberal_parsing: true # 宽松解析,支持行尾空字段、非标格式
    ) do |row|
      # 统一处理空值,避免空字符串入库
      row_hash = row.to_hash.transform_values { |val| val == ' ' ? nil : val&.strip }
      model_class.create!(row_hash)
      puts "Insert on table #{model_class.name} complete"
    end
  end
end

兜底方案

如果调整参数后仍有换行符报错,可手动逐行读取后解析,跳过CSV的自动行分割逻辑:

def import_csv_into_db
  Dir.foreach(Rails.root.join('db', 'csv_export')) do |filename|
    next if ['.', '..', 'extract_db_into_csv.sh', 'import_csv.rb'].include?(filename)
    file_path = Rails.root.join('db', 'csv_export', filename)
    model_class = File.basename(filename, File.extname(filename)).classify.constantize
    lines = File.readlines(file_path).map(&:strip).reject(&:empty?)
    headers = CSV.parse_line(lines.first, liberal_parsing: true)
    lines[1..].each do |line|
      row = CSV.parse_line(line, headers: headers, liberal_parsing: true)
      row_hash = row.to_hash.transform_values { |val| val == ' ' ? nil : val&.strip }
      model_class.create!(row_hash)
      puts "Insert on table #{model_class.name} complete"
    end
  end
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:48:02