我从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?
答案 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
答案 1 :(得分:1)
如果它包含BOM,我没有找到直接从远程文件中读取的方法。所以我使用Tempfile文件创建临时文件,然后我用&#39; r:bom | utf-8&#39;:
执行CSV.opendoc = 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
现在,它似乎在解析文件。