Ruby не удалось проанализировать файл CSV: CSV::MalformedCSVError (недопустимое цитирование в строке 1.)
Ubuntu 12.04 LTS
Ruby ruby 1.9.3dev (2011-09-23, редакция 33323) [i686-linux]
Рельсы 3.2.9
Ниже приводится содержание моего полученного файла CSV:
"date/time","settlement id","type","order id","sku","description","quantity","marketplace","fulfillment","order city","order state","order postal","product sales","shipping credits","gift wrap credits","promotional rebates","sales tax collected","selling fees","fba fees","other transaction fees","other","total"
"Mar 1, 2013 12:03:54 AM PST","5481545091","Order","108-0938567-7009852","ALS2GL36LED","Solar Two Directional 36 Bright White LED Security Flood Light with Motion Activated Sensor","1","amazon.com","Amazon","Pasadena","CA","91104-1056","43.00","3.25","0","-3.25","0","-6.45","-3.75","0","0","32.80"
Однако, когда я пытаюсь проанализировать файл CSV, я получаю сообщение об ошибке:
1.9.3dev :016 > options = { col_sep: ",", quote_char:'"' }
=> {:col_sep=>",", :quote_char=>"\""}
1.9.3dev :022 > CSV.foreach("/tmp/my_data.csv", options) { |row| puts row }
CSV::MalformedCSVError: Illegal quoting in line 1.
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1925:in `block (2 levels) in shift'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1887:in `each'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1887:in `block in shift'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1849:in `loop'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1849:in `shift'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1791:in `each'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1208:in `block in foreach'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1354:in `open'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1207:in `foreach'
from (irb):22
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/bin/irb:16:in `<main>'
Затем я попытался упростить данные, т.е.
"name","age","email"
"jignesh","30","jignesh@example.com"
Однако все равно я получаю ту же ошибку:
1.9.3dev :023 > CSV.foreach("/tmp/my_data.csv", options) { |row| puts row }
CSV::MalformedCSVError: Illegal quoting in line 1.
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1925:in `block (2 levels) in shift'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1887:in `each'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1887:in `block in shift'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1849:in `loop'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1849:in `shift'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1791:in `each'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1208:in `block in foreach'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1354:in `open'
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/lib/ruby/1.9.1/csv.rb:1207:in `foreach'
from (irb):23
from /home/jigneshgohel/.rvm/rubies/ruby-1.9.3-rc1/bin/irb:16:in `<main>'
Я снова попытался упростить данные следующим образом:
name,age,email
jignesh,30,jignesh@example.com
и это работает. Смотрите вывод ниже:
1.9.3dev :024 > CSV.foreach("/tmp/my_data.csv") { |row| puts row }
name
age
email
jignesh
30
jignesh@example.com
=> nil
Но я буду получать файлы CSV, содержащие данные в кавычках, поэтому решение по удалению кавычек на самом деле не требуется. Я не могу выяснить, что является причиной ошибки: CSV:: MalformedCSVError: Неверное цитирование в строке 1. в моих предыдущих примерах,
Я убедился, что в CSV нет начальных / конечных пробелов, включив "Показать пробельные символы" и "Показать окончания строк" в моем текстовом редакторе. Также я проверил кодировку, используя следующую.
1.9.3dev :026 > File.open("/tmp/my_data.csv").read.encoding
=> #<Encoding:UTF-8>
Примечание. Я тоже пытался использовать CSV.read, но при этом методе возникла та же ошибка.
Кто-нибудь может помочь мне выбраться из проблемы и заставить меня понять, в чем дело?
=====================
Я только что нашел следующий пост по адресу: http://www.ruby-forum.com/topic/448070 и попробовал следующее:
file_data = file.read
file_data.gsub!('"', "'")
arr_of_arrs = CSV.parse(file_data)
arr_of_arrs.each do |arr|
Rails.logger.debug "=======#{arr}"
end
и получил следующий вывод:
=======["\xEF\xBB\xBF'date/time'", "'settlement id'", "'type'", "'order id'", "'sku'", "'description'", "'quantity'", "'marketplace'", "'fulfillment'", "'order city'", "'order state'", "'order postal'", "'product sales'", "'shipping credits'", "'gift wrap credits'", "'promotional rebates'", "'sales tax collected'", "'selling fees'", "'fba fees'", "'other transaction fees'", "'other'", "'total'"]
=======["'Mar 1", " 2013 12:03:54 AM PST'", "'5481545091'", "'Order'", "'108-0938567-7009852'", "'ALS2GL36LED'", "'Solar Two Directional 36 Bright White LED Security Flood Light with Motion Activated Sensor'", "'1'", "'amazon.com'", "'Amazon'", "'Pasadena'", "'CA'", "'91104-1056'", "'43.00'", "'3.25'", "'0'", "'-3.25'", "'0'", "'-6.45'", "'-3.75'", "'0'", "'0'", "'32.80'"]
который неправильно читал данные, так как используемый по умолчанию col_sep - это запятая. Однако я попытался использовать опцию quote_char вот так:
arr_of_arrs = CSV.parse(file_data, :quote_char => "'")
но это закончилось следующей ошибкой:
CSV::MalformedCSVError (Illegal quoting in line 1.):
Спасибо джинеш
11 ответов
quote_chars = %w(" | ~ ^ & *)
begin
@report = CSV.read(csv_file, headers: :first_row, quote_char: quote_chars.shift)
rescue CSV::MalformedCSVError
quote_chars.empty? ? raise : retry
end
это не идеально, но работает большую часть времени.
NB CSV.parse
принимает те же параметры, что и CSV.read
можно использовать файл или данные из памяти
Ананд, спасибо за предложение по кодированию. Это решило проблему незаконного цитирования для меня.
Примечание. Если вы хотите, чтобы итератор пропустил строку заголовка, добавьте headers: :first_row
, вот так:
CSV.foreach("test.csv", encoding: "bom|utf-8", headers: :first_row)
У меня просто была такая проблема, и я обнаружил, что CSV не любит пробелы между символом кавычки и символом кавычки. Как только я удалил те, все прошло хорошо. Итак, у меня было:
12, "N", 12, "Pacific/Majuro"
но однажды я вырубил пробелы, используя
.gsub(/,\s+\"/,',\"')
в результате чего
12,"N", 12,"Pacific/Majuro"
все прошло нормально.
Версия Rails 6, ruby 2.4+
CSV.foreach(file, liberal_parsing: true, headers: :first_row) do |row|
// do whatever
end
Из этой ветки передайте опцию:quote_char => "|"
CSV.read(filename, :quote_char => "|")
Добавить
:liberal_parsing => true
аргумент
CSV.read
и это должно решить некоторые проблемы с "незаконным цитированием"
У меня была проблема с товарным знаком, который выбрасывал эту ошибку.
Символ торговой марки переводится как \"! В UTF-8, поэтому это был открытый символ кавычки, который выдавал ошибку. Поэтому я сделал это:
.gsub!("\"!", "")
А потом я попытался создать свой объект CSV, и он работал нормально.
Я попытался прочитать файл и получить строку, а затем проанализировать их в таблице CSV, но получил исключение:
CSV.read(File.read('file.csv'), headers: true)
CSV::MalformedCSVError: Unclosed quoted field on line 1794.
Ни один из приведенных здесь ответов не сработал для меня. Фактически, тому, кто набрал наибольшее количество голосов, потребовалось так много времени, чтобы разобрать, что в итоге я прекратил казнь. Скорее всего, это вызвало много исключений, и это время стоит больших файлов.
Еще более проблематично, что ошибка не очень полезна, так как это большой CSV-файл. Где именно линия 1794? Я открыл файл в LibreOffice, который открылся без проблем. Строка 1794 была последней строкой данных файла CSV. Таким образом, очевидно, проблема была связана с концом файла CSV. Я решил проверить содержимое в виде строки с File.read. Я заметил, что строка заканчивается символом возврата каретки:
,\"\"\r
Я решил использовать chomp и удалить возврат каретки в конце файла. Обратите внимание, что если $/ не было изменено из стандартного разделителя записей Ruby, chomp также удаляет символы возврата каретки (то есть удаляет \n, \r и \r\n).
CSV.parse(File.read('file.csv' ).chomp, headers: true)
=> #<CSV::Table mode:col_or_row row_count:1794>
И это сработало. Проблема заключалась в символе \ r в конце файла.
У меня была эта проблема в строке вродеAgricover 22040169 Access; TonnoSport
Проблема в том, что синтаксический анализатор CSV ожидает, в случае, если они кажутся, полностью окружить текст с разделителями-запятыми.
решение использовать человека в кавычках, кроме"
которые, как я был уверен, не появятся в моих записях:
CSV.parse(file_path, headers: true, :quote_char => "|")
Для получения дополнительной информации читать?
https://ruby-doc.org/stdlib-2.6.1/libdoc/csv/rdoc/CSV.html#class-CSV-label-Reading
Менее распространенная причина этой ошибки — когда файл не заключает в кавычки поля , но
quote_char
по-прежнему установлен (по умолчанию это
"
) и одно или несколько полей содержат этот символ.
Чтобы полностью отключить цитирование полей, установите
quote_char: nil
в параметрах разбора.
Например, при наличии файла
/tmp/people.csv
как это:
Actor,Dwayne "The Rock" Johnson,1972-05-02
Character,TV's Frank,1956-08-30
Это можно разобрать с помощью этого:
CSV.read('/tmp/people.csv', quote_char: nil)
Попробуйте эту подсказку:
- Откройте файл CSV в текстовом редакторе.
- Выберите весь файл и скопируйте его
- Откройте новый текстовый файл
- Вставьте данные CSV в новый файл и сохраните новый файл
- Импортируйте новый CSV-файл