Ruby не смог разобрать CSV файл: CSV:: MalformedCSVError (незаконное цитирование в строке 1.) - программирование
Подтвердить что ты не робот

Ruby не смог разобрать CSV файл: CSV:: MalformedCSVError (незаконное цитирование в строке 1.)

Ubuntu 12.04 LTS

Ruby ruby ​​1.9.3dev (2011-09-23 версия 33323) [i686-linux]

Rails 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>'

Затем я попытался упростить данные i.e.

"name","age","email"
"jignesh","30","[email protected]"

однако все же я получаю ту же ошибку:

      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,[email protected]

и он работает. Посмотрите ниже:

  1.9.3dev :024 > CSV.foreach("/tmp/my_data.csv") { |row| puts row }
  name
  age
  email
  jignesh
  30
  [email protected]
   => 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.):

Спасибо, Jignesh

4b9b3361

Ответ 1

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

он не идеален, но он работает большую часть времени.

N.B. CSV.parse принимает те же параметры, что и CSV.read, поэтому можно использовать файл или данные из памяти

Ответ 2

У меня была такая проблема, и я обнаружил, что CSV не любит пробелов между col-sep и символом кавычки. Как только я удалил все, все пошло нормально. Поэтому у меня было:

12,  "N",  12, "Pacific/Majuro"

но как только я вычеркнул пробелы, используя

.gsub(/,\s+\"/,',\"')

в результате чего

12,"N",  12,"Pacific/Majuro"

все пошло нормально.

Ответ 3

Ананд, спасибо за предложение кодирования. Это разрешило проблему незаконного цитирования для меня.

Примечание. Если вы хотите, чтобы итератор пропустил строку заголовка, добавьте headers: :first_row, например:

CSV.foreach("test.csv", encoding: "bom|utf-8", headers: :first_row)

Ответ 4

У меня возникла проблема с символом товарного знака, который выдавал эту ошибку.

Символ товарного знака преобразуется в \"! в UTF-8, поэтому это был открытый котировочный символ, который выдавал ошибку. Поэтому я сделал это:

.gsub!("\"!", "")

И затем я попытался создать свой CSV-объект, и он работал нормально.

Ответ 5

Я попытался прочитать файл и получить строку, а затем проанализировать их в таблице 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 в конце файла.

Ответ 6

Попробуйте этот намек:

  • Откройте CSV файл в текстовом редакторе
  • Выберите весь файл и скопируйте его
  • Откройте новый текстовый файл
  • Вставьте CSV-данные в новый файл и сохраните новый файл
  • Импортируйте новый CSV файл