Ruby CSV – 第1行中的非法引用.CSV :: MalformedCSVError

我从csv文件中读取时遇到问题。 文件来自Windows,所以我想有一些编码问题。 我的代码如下所示:

CSV.open(path, 'w', headers: :first_row, col_sep: ';', row_sep: "\r\n", encoding: 'utf-8') do |csv| CSV.parse(open(doc.file.url), headers: :first_row, col_sep: ';', quote_char: "\"", row_sep: "\r\n", encoding: 'utf-8').each_with_index do |line, index| csv << line.headers if index == 0 # do something wiht row csv << line end end 

我必须打开现有文件并从中填写一些列。 所以我只是创建新文件。 现有文件存储在Dropbox上,因此我必须使用open方法。

问题是我在这一行中收到错误:

  CSV.parse(open(doc.file.url), headers: :first_row, col_sep: ';', quote_char: "\"", row_sep: "\r\n", encoding: 'utf-8').each_with_index do |line, index| 

错误是:

  Illegal quoting in line 1. CSV::MalformedCSVError 

我检查并且好像我文件中没有BOM字符(不确定是否正确检查)。 问题似乎是引用字符。 为文件中的每一行抛出exception。

这是导致我出现问题的文件: https : //dl.dropboxusercontent.com/u/3900955/geo_bez_adresu_10_do_testow_small.csv

我尝试了StackOverflow的不同方法,但没有任何帮助,例如我将我的代码更改为:

 CSV.open(path, 'w', headers: :first_row, col_sep: ';', row_sep: "\r\n", encoding: 'utf-8') do |csv| open(doc.file.url) do |f| f.each_line do |line| CSV.parse(line, 'r:bom|utf-8') do |row| csv << row end end end end 

但它没有帮助。 我将非常感谢您解析此文件的任何帮助。

=======编辑=========

当我在Windows上安装相同的文件,编码ANSI为UTF-8(在Notepad ++中)时,我可以正确解析文件。 从这个讨论什么是“ANSI as UTF-8”以及如何使fputcsv()生成带有BOM的UTF-8? ,好像我在原始文件中有BOM。 如果我的文件是BOM,我如何检查Ruby以及如何使用BOM解析csv文件?

CSV.parse()在其第一个参数上需要一个字符串,但您要传递一个File对象。 会发生什么是parse()得到解析(file object).to_s的扩展值而导致错误。

更新

要使用BOM读取文件,您可以:

 CSV.new(File.open('file.csv', 'r:bom|utf-8'), col_sep: ';').each do |row| ... end 

参考: https : //stackoverflow.com/a/7780559/445221

如果它包含BOM,我没有找到任何直接从远程文件中读取的方法。 所以我使用Tempfile文件创建临时文件,然后使用’r:bom | utf-8’执行CSV.open:

 doc = Document.find(doc_id) path = "#{Rails.root.join('tmp')}/#{doc.name.split('.').first}_#{Time.now.to_i}.csv" file = Tempfile.new(["#{doc.name.split('.').first}_#{Time.now.to_i}", '.csv']) file.binmode file << open(doc.file.url).read file.close CSV.open(path, 'w', headers: :first_row, col_sep: ';', row_sep: "\r\n", encoding: 'utf-8') do |csv| CSV.open(file.path, 'r:bom|utf-8', headers: :first_row, col_sep: ';', quote_char: "\"", row_sep: "\r\n").each_with_index do |line, index| # do something end end 

现在,它似乎解析文件。