2011-11-10 13 views
21

Mam niewiarygodny czas na zaimportowanie pliku CSV w Ruby-1.9.2.Importowanie błędu cytowania CSV doprowadza mnie do szału

Plik Próbuję analizować posiada:

  • przecinki w kolumnach
  • cudzysłowy pomiędzy kolumnami
  • używa '@' jako: col_sep

csv.txt (reprezentatywne wejście, rzeczywisty to 101k linii):

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

Mój kod:

require 'csv' 

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

My pożądane wyjście:

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

Co mam wyjścia:

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

on mówi, że są niezamknięte notowane feilds, ale widzę, że Cytaty otwierają się i zamykają.

Ucieczka z cytatów nic nie robi. Otrzymuję ten sam błąd ([email protected]""seal"" r...). Zmiana ich na pojedyncze cudzysłowy powoduje, że działa ([email protected]'seal' r...). Problem polega na tym, że POTRZEBUJĘ, aby były w podwójnych cudzysłowach.

Wszelkie pomysły?

Odpowiedz

56

Myślę, że problem polega na tym, że CSV próbuje interpretować "seal" jako pojedynczą cytowaną kolumnę; ale nie wygląda na to, że parser jest zdezorientowany, ponieważ cytaty mają otaczać kolumny. Nie widzę żadnej opcji informowania CSV, że kolumny nie są cytowane, ale można je otoczyć, ustawiając :quote_char na coś, co nigdy nie wystąpi. Jeśli używasz UTF-8, a następnie można bezpiecznie stosować zerowy bajt jako „cytując znaku, który nigdy nie będzie występować”:

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

to powinno działać tak długo, jak żaden z kolumn są notowane.

+2

+1 Specyfikacja CSV jest tak całkowicie nadużywany i ignorowany, podobnie jak HTML. W obu przypadkach próbuję naprawić dane zanim oddam je do analizatora składni. Myślę, że byłoby to również rozwiązanie tego problemu, ale lubię, jak oszukujesz parser za pomocą 'quote_char =>" \ x00 "'. Dobra robota. –

+2

Mam UTF-16 pochodzący z 'bcp' MSSQL dump, który faktycznie ma znak nul. Dla zabawy wybrałem postać bałwana (☃) jako zastępcę. :) –

+0

Ten trik '' \ x00 "' działa pięknie :-) – Avishai

Powiązane problemy