2011-09-08 1 views
2

CSVMapper Gem을 사용하여 CSV 파일의 일부 레코드를 Rails 3 모델로 가져옵니다.레일스에서 ​​CSV 가져 오기 - 영문자가 아닌 UTF-8의 바이트 시퀀스가 ​​잘못되었습니다.

r = import('doc/socios_full.csv') do 
    map_to Associate 
    after_row lambda{|row, associate| associate.save } 
    start_at_row 1 
    [group,member,family_relationship_code,family_relationship_description,last_name,names,...] 
#The previous line is actually longer, with more atts, but it's been cut to explain the example 
end 

:

어쨌든 (그것이 내가이 작업을 수행하는 가장 쉬운 방법을 발견 한 것입니다 때문에이 보석을 사용), 나는 레코드를 가져올 사용하고 코드는 다음과 같다 파서가 ó, é, ñ, í, °...과 같은 일부 비영어권 문자를 접할 때를 제외하고는 매우 잘 작동합니다. 나는 다음과 같은 오류 얻을 때 그건 : 파서가 다른 영어 이외의 문자를 찾을 때까지 나는이 모든 문자를 대체하는 경우 때문에

ArgumentError: invalid byte sequence in UTF-8 
    from /home/bcb/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/csv.rb:1831:in `sub!' 
    from /home/bcb/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/csv.rb:1831:in `block in shift' 
    from /home/bcb/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/csv.rb:1825:in `loop' 
    from /home/bcb/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/csv.rb:1825:in `shift' 
    from /home/bcb/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/csv.rb:1767:in `each' 
    from /home/bcb/.rvm/gems/ruby-1.9.2-p136/gems/csv-mapper-0.5.1/lib/csv-mapper.rb:106:in `each_with_index' 
    from /home/bcb/.rvm/gems/ruby-1.9.2-p136/gems/csv-mapper-0.5.1/lib/csv-mapper.rb:106:in `import' 
    from (irb):63 
    from /home/bcb/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.9/lib/rails/commands/console.rb:44:in `start' 
    from /home/bcb/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.9/lib/rails/commands/console.rb:8:in `start' 
    from /home/bcb/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.9/lib/rails/commands.rb:23:in `<top (required)>' 
    from script/rails:6:in `require' 
    from script/rails:6:in `<main>' 

나는이 정말 확신을 문제가 사라집니다. 문제는 내가 50k 레코드 파일을 가지고 있기 때문에 매번 이러한 모든 레코드를 가져올 수 있다고 생각할 수있는 각 문자를 검색하는 데는 많은 시간이 소요됩니다.

이러한 오류를 무시하고 파서가 계속 진행될 수있는 방법이 있습니까? 또는이 CSV 파일을보다 쉽게 ​​가져올 수 있습니까?

+0

원래 어디에서 왔는지 어떻게 CSV 파일이 인코딩 알거나합니까? –

+0

네, IT는 스페인 수출 업체 인 스페인 조직에서 나왔습니다. 나는 그것을 해결했다! – bruno077

답변

3

을, 이것은 외부 보석을 사용하는 것보다 레일 3 모델로 CSV 파일을 가져 오기위한 훨씬 쉽게 솔루션입니다 :

require 'csv' 
    CSV.foreach('doc/socios_full.csv') do |row| 
     record = Associate.new(
      :media_format => row[0], 
      :group => row[0], 
      :member => row[1], 
      :family_relationship_code => row[2], 
      :family_relationship_description => row[3], 
      :last_name => row[4], 
      :names => row[5], 
      ... 
     ) 
     record.save! 
    end 

비 영어 문자 (75k 가져 오기 파일을 사용해 본 사람)와도 완벽하게 작동합니다. 희망은 누군가에게 도움이되기를 바랍니다.

+0

니스, 나는 "그냥 손으로 그것을하고 가서"접근 방식의 큰 팬이야. –

+0

전적으로 동의합니다. 게다가, 외부 보석이 적을수록 좋습니다. (나는 루비와 레일을 아직도 배우고있어 그래서 나는 매일 조금 더 배우려고 노력한다) – bruno077

1

어쩌면,이 같은 시도 할 수 있습니다 : 다른 접근 방식을 해결

csv_string.force_encoding('ISO-8859-1') 
+1

"r"은 배열이므로 force_encoding 메서드가 작동하지 않습니다. – bruno077

14

이처럼 수행

CSV.foreach(filename, :headers => true , :encoding => 'ISO-8859-1') do |row| 

내가 MS 엑셀로 저장 한 CSV 파일에서 읽으려고 같은 문제가 있었다. 인코딩을 옵션으로 지정할 수 있습니다. 기본적으로 UTF-8을 사용한다고 가정합니다.

0

다음과 같은 방법을 사용하면 CSV가 올바른 헤더 이름을 포함 할 것이라고 확신 가정 모든 모델에서 작동합니다 :

def self.import(file) 
    CSV.foreach(file.path, headers: true) do |row| 
     obj = self.new 
     obj.attributes.each_key do |attribute| 
     index = row.headers.index(attribute) 
     obj.send("#{attribute}=",row[index]) if index 
     end 
     obj.save 
    end 
    end 
관련 문제