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

时间:2014-08-10 20:29:41

标签: ruby csv

我从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字符(不确定是否正确检查)。问题似乎是引用字符。为文件中的每一行抛出异常。

这是导致我出现问题的文件: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 

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

======= edit =========

当我在Windows上使用编码ANSI作为UTF-8(在Notepad ++中)保护同一文件时,我可以正确解析文件。从这个讨论What is "ANSI as UTF-8" and how can I make fputcsv() generate UTF-8 w/BOM?,我似乎在原始文件中有BOM。如果我的文件是BOM,以及如何使用BOM解析csv文件,我如何检查Ruby?

2 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:1)

如果它包含BOM,我没有找到直接从远程文件中读取的方法。所以我使用Tempfile文件创建临时文件,然后我用&#39; r:bom | utf-8&#39;:

执行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 

现在,它似乎在解析文件。

相关问题