2011-11-10 10 views
21

Ho avuto un incredibile momento nel tentativo di importare un file CSV in ruby-1.9.2.L'importazione dell'errore di quotatura CSV mi sta facendo impazzire

Il file che sto cercando di analizzare ha:

  • virgole all'interno di colonne
  • citazioni all'interno di colonne
  • utilizza un '@' come: col_sep

csv.txt (input rappresentativo, uno reale è linee 101k):

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

Il mio codice:

require 'csv' 

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

mio output desiderato:

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

ciò che ho per l'uscita:

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

Si dice che ci sono feilds citati non chiusi, ma posso vedere che il le citazioni si aprono e si chiudono

L'escape delle virgolette non fa nulla. Ottengo lo stesso errore ([email protected]""seal"" r...). La loro modifica in virgolette singole lo fa funzionare ([email protected]'seal' r...). Il problema è che ho bisogno che siano tra virgolette.

Qualche idea?

risposta

56

Penso che il problema è che CSV sta cercando di interpretare "seal" come una singola colonna quotata; ma, non appare come @"seal"@ così il parser si confonde perché le virgolette dovrebbero circondare le colonne. Non vedo alcuna opzione per dire a CSV che le colonne non sono quotate ma puoi aggirarle intorno impostando :quote_char in qualcosa che non si verificherà mai. Se stai usando UTF-8, è possibile utilizzare in modo sicuro un byte zero come "personaggio citazione che non potrà mai verificarsi":

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

Questo dovrebbe funzionare fintanto che nessuno dei vostri colonne sono quotati.

+2

+1 La specifica CSV. è così completamente abusato e ignorato, in modo simile all'HTML. Per entrambi, ci sono volte in cui ricorro ai dati prima di consegnarlo al parser. Penso che sarebbe una soluzione anche per questo problema, ma mi piace come stai prendendo in giro il parser con 'quote_char =>" \ x00 "'. Bel lavoro. –

+2

Ho UTF-16 proveniente da un dump MSSQL 'bcp' che in realtà ha il carattere nul. Solo per divertimento ho scelto il personaggio del pupazzo di neve (☃) come alternativa. :) –

+0

Questo trucco "" \ x00 "' funziona magnificamente :-) – Avishai

Problemi correlati