2011-11-10 15 views
21

He estado teniendo un tiempo increíble tratando de importar un archivo CSV en ruby-1.9.2.Importación de CSV error de cotización me está volviendo loco

El archivo que estoy tratando de analizar tiene:

  • comas dentro de columnas
  • citas dentro de columnas
  • utiliza un '@' como: col_sep

csv.txt (entrada representativa, la verdadera es 101k líneas):

㔾@㔾@jié@"seal" radical in Chinese characters, (Kangxi radical 26) 

Mi código:

require 'csv' 

CSV.foreach("/Users/adam/Desktop/csvtest.txt", {:col_sep => "@"}) do |row| 
    puts row.to_s 
end 

Mi salida deseada:

["㔾", "㔾", "jié", "\"seal\" radical in Chinese characters, (Kangxi radical 26)"] 

Lo que me pasa por la salida:

CSV::MalformedCSVError: Unclosed quoted field on line 1. 
from /Users/adam/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/CSV.rb:1910:in `block in shift' 
from /Users/adam/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/CSV.rb:1825:in `loop' 
from /Users/adam/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/CSV.rb:1825:in `shift' 
from /Users/adam/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/CSV.rb:1767:in `each' 
from /Users/adam/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/CSV.rb:1202:in `block in foreach' 
from /Users/adam/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/CSV.rb:1340:in `open' 
from /Users/adam/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/CSV.rb:1201:in `foreach' 
from (irb):31 
from /Users/adam/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>' 

Se dice que hay feilds citados no cerradas, pero puedo ver que la Las citas se abren y cierran.

Escapar de las comillas no hace nada. Obtengo el mismo error ([email protected]""seal"" r...). Cambiarlos a comillas simples lo hace funcionar ([email protected]'seal' r...). El problema es que NECESITO que estén entre comillas dobles.

¿Alguna idea?

Respuesta

56

Creo que el problema es que CSV está tratando de interpretar "seal" como una sola columna entre comillas; pero, no aparece como @"seal"@, por lo que el analizador se confunde porque se supone que las comillas rodean a las columnas. No veo ninguna opción para decirle a CSV que las columnas no están entre comillas, pero puede evitarlo estableciendo :quote_char en algo que nunca ocurrirá. Si está utilizando UTF-8, puede utilizar de manera segura un byte cero como su "carácter de comillas que nunca va a ocurrir":

CSV.foreach(filename, :col_sep => "@", :quote_char => "\x00") do |row| 
    #... 
end 

Esto debería funcionar siempre y cuando ninguno de sus columnas se cita.

+2

+1 La especificación CSV. es tan completamente abusado e ignorado, de manera similar a HTML. Para ambos, hay ocasiones en que recurro a arreglar los datos antes de pasarlos al analizador sintáctico. Creo que también sería una solución para este problema, pero me gusta cómo engañas al analizador con 'quote_char =>" \ x00 "'. Buen trabajo. –

+2

Tengo UTF-16 procedente de un volcado de MSCQL 'bcp' que en realidad tiene el carácter nul. Solo por diversión elegí el personaje de muñeco de nieve (☃) como suplente. :) –

+0

Este truco '' \ x00 "' funciona muy bien :-) – Avishai

Cuestiones relacionadas