ruby csv malformed

Ruby no puede analizar un archivo CSV: CSV:: MalformedCSVError(cita ilegal en la línea 1)



(6)

Ubuntu 12.04 LTS

Ruby Ruby 1.9.3dev (2011-09-23 revisión 33323) [i686-linux]

Rieles 3.2.9

El siguiente es el contenido de mi archivo CSV recibido:

"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"

Sin embargo, cuando intento analizar el archivo CSV, aparece un error:

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

Entonces intenté simplificar los datos, es decir

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

Sin embargo todavía estoy recibiendo el mismo error:

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

De nuevo intenté simplificar los datos de esta manera:

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

y funciona. Vea la salida a continuación:

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

Pero recibiré los archivos CSV con los datos citados, por lo que eliminar la solución de comillas no es lo que realmente estoy buscando. No puedo averiguar qué está causando el error: CSV :: MalformedCSVError: cita ilegal en la línea 1. en mis ejemplos anteriores .

He verificado que en el CSV no hay espacios iniciales / finales al habilitar "Mostrar caracteres de espacio en blanco" y "Mostrar finales de línea" en mi editor de texto. También verifiqué la codificación utilizando lo siguiente.

1.9.3dev :026 > File.open("/tmp/my_data.csv").read.encoding => #<Encoding:UTF-8>

Nota: Intenté usar CSV.read también, pero el mismo error con ese método.

¿Alguien por favor puede ayudarme a salir del problema y hacerme entender dónde está yendo mal?

=====================

Acabo de encontrar la siguiente publicación en: http://www.ruby-forum.com/topic/448070 y probé lo siguiente:

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

y obtuvo la siguiente salida:

=======["/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''"]

que arruinó la lectura de los datos correctamente ya que el col_sep predeterminado utilizado es un carácter de coma. Sin embargo, intenté usar la opción quote_char como esta:

arr_of_arrs = CSV.parse(file_data, :quote_char => "''")

pero terminó el siguiente error:

CSV::MalformedCSVError (Illegal quoting in line 1.):

Gracias jignesh


Acabo de tener un problema como este y descubrí que a CSV no le gustan los espacios entre el col-sep y el carácter de cita. Una vez que quité todo, todo salió bien. Así que tuve:

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

pero una vez que saqué los espacios usando

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

Resultando en

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

todo salió bien.


Anand, gracias por la sugerencia de codificación. Esto resolvió el problema de cotización ilegal para mí.

Nota: Si desea que el iterador se salte sobre la fila del headers: :first_row agregue los headers: :first_row , así:

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


Intenté leer el archivo y obtener una cadena y luego analizarla en una tabla CSV, pero recibí una excepción:

CSV.read(File.read(''file.csv''), headers: true) CSV::MalformedCSVError: Unclosed quoted field on line 1794.

Ninguna de las respuestas proporcionadas aquí funcionó para mí. De hecho, el que obtuvo el mayor número de votos tardó tanto tiempo en analizar que finalmente terminé la ejecución. Lo más probable es que haya generado muchas excepciones, y ese tiempo es costoso en un archivo grande.

Aún más problemático, el error no es tan útil, ya que es un archivo CSV grande. ¿Dónde está exactamente la línea 1794? Abrí el archivo en LibreOffice que se abrió sin problemas. La línea 1794 fue la última fila de datos del archivo csv. Al parecer, el problema tenía que ver con el final del archivo CSV. Decidí inspeccionar el contenido como una cadena con File.read. Noté que la cadena terminó con un carácter de retorno de carro:

,/"/"/r

Decidí usar chomp y eliminar el retorno de carro al final del archivo. Tenga en cuenta si $ / no se ha cambiado desde el separador de registros de Ruby predeterminado, entonces chomp también elimina los caracteres de retorno de carro (es decir, eliminará / n, / r y / r / n).

CSV.parse(File.read(''file.csv'' ).chomp, headers: true) => #<CSV::Table mode:col_or_row row_count:1794>

Y funcionó. El problema fue el carácter / r al final del archivo.


Prueba esta sugerencia:

  1. Abra su archivo CSV en un editor de texto
  2. Selecciona todo el archivo y cópialo.
  3. Abre un nuevo archivo de texto
  4. Pegue los datos CSV en el nuevo archivo y guarde el nuevo archivo
  5. Importa tu nuevo archivo CSV

Tuve un problema con el carácter de marca registrada que estaba lanzando este error.

El carácter de marca registrada se traduce a / "! En UTF-8, por lo que fue el símbolo de comillas abiertas el que generó el error. Así que hice esto:

.gsub!("/"!", "")

Y luego intenté crear mi objeto CSV y funcionó bien.


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

No es perfecto pero funciona la mayor parte del tiempo.

NB CSV.parse toma los mismos parámetros que CSV.read , por lo que se puede usar un archivo o datos de la memoria