Проблемы при попытке проанализировать CSV-файл с умлаутом и т. Д. С помощью Ruby 1.8 / FasterCSV - PullRequest
2 голосов
/ 20 февраля 2011

У меня есть CSV-файл с такими строками:

...,"Städtische Galerie im Lenbachhaus",...

Я использую Ruby 1.8 с гемом FasterCSV, например:

FasterCSV.foreach(file, :encoding => 'u', :headers => :first_row) do |r|
    as = ImportObject.create!(r.to_hash)
end

Для большинства строкон работает нормально, но для этих строк поле со специальным символом усекается, поэтому мы сохраняем "St" в БД.

Я положил $ KCODE = "u" и с / без кодировкиопция, но безрезультатно.

БД - MySQL.

РЕДАКТИРОВАТЬ:

Я попытался передать код до Heroku (Postgres) и теперь получаю новую ошибку:

2011-02-19T17: 19: 01-08: 00 приложение [web.1]: ActiveRecord :: StatementInvalid (PGError: ОШИБКА: недопустимая последовательность байтов для кодирования «UTF8»: 0xe46474

2011-02-19T17: 19: 01-08: 00 app [web.1]: СОВЕТ: Эта ошибка также может произойти, если последовательность байтов не соответствует кодировке, ожидаемой сервером, который управляется "client_encoding".

2011-02-19T17: 19: 01-08: 00 app [web.1]:: INSERT INTO" import_objects "(..." title ", ...) VALUES (..., 'St? Dtische Galerie im Lenbachhaus ', ...) ВОЗВРАЩАЯСЯ "id"):

: (

Ответы [ 3 ]

3 голосов
/ 20 февраля 2011

Вероятно, проблема связана с кодировкой файлов, как вы и предполагали.Наиболее вероятным сценарием является то, что ваш файл фактически не закодирован в UTF-8, поэтому остальная часть вашего приложения не может распознать чужую кодировку.Также возможно - но я считаю весьма маловероятным - что один из байтов, используемых в кодировке, является кавычкой или запятой в ASCII, что приведет к путанице в FasterCSV при разборе данных.

Сначала создайте тестовый файл с «строкой проблемы» в файле CSV.Далее прочитайте данные в файле:

text_in = File.read('data.csv')

Теперь вам нужно конвертировать его.Проблема в том, что вы не знаете, что это такое.Вам придется попробовать несколько разных вещей.Я предпочитаю, чтобы текст был в кодировке Latin-1.

require 'iconv'
text_out = Iconv.conv("UTF8", "LATIN1", text_in)

Теперь попробуйте импортировать эти данные.Кроме того, вы можете записать на диск и открыть его, и посмотреть, правильно ли он закодирован.

Но, честно говоря, вы можете сделать это вне Ruby намного проще.

$ iconv -t UTF8 -f LATIN1 < data.csv > data_conv.csv

Дополнительное чтение:

1 голос
/ 20 февраля 2011

Вы не говорите, какой тип базы данных вы используете, но вполне возможно, что БД не настроена для UTF-8, а вместо этого ожидает ASCII. Вбрасывание в него символов, отличных от ASCII, может привести к усеченной строке, отсутствующему символу или символу, замененному заполнителем, в зависимости от базы данных и того, какой гем или ORM вы используете для общения с ней. Когда я строю базу данных, я проверяю, что она настроена для UTF-8, или я проверяю, что текст, который я вставляю в нее, закодирован, чтобы он мог совершать циклические обходы без повреждения или потери. Я усвоил этот урок так же, как ты, трудный путь.

Проверьте журнал базы данных и / или проверьте свой код, чтобы увидеть, можно ли включить ведение журнала и сообщения об ошибках и предупреждения для вставок базы данных.

Легко отключить предупреждения и ошибки с большим количеством баз данных, но во время разработки вы не хотите этого делать. Эти сообщения важны и могут сигнализировать о больших проблемах. Игнорирование их и отправка кода в производство может стать реальным рецептом для бессонных ночей.

1 голос
/ 20 февраля 2011

Проблема не в FasterCSV, так как в моем тестировании у FasterCSV не было проблем с чтением этих данных. Например:

>> FasterCSV.parse("a,Städtische Galerie im Lenbachhaus,b,ä", :headers => [:a,:b,:c,:d]) do |r|
|    r = r.to_hash
|    p r
|    puts r[:d]
|  end  
{:c=>"b", :a=>"a", :d=>"\303\244", :b=>"Städtische Galerie im Lenbachhaus"}
ä

Обратите внимание, что Ruby 1.8 не обрабатывает символы Юникода должным образом, но в основном это влияет на такие вещи, как String#length. Например, Ruby вернет длину этой строки как 34 вместо 33. Однако это не повлияет, пока вы не сделаете что-то со строкой, например, запустите проверку на ней.

>> "Städtische Galerie im Lenbachhaus".length
=> 34
>> "Stadtische Galerie im Lenbachhaus".length
=> 33

Так что я думаю, это что-то вроде ImportObject или как настроено ваше соединение с базой данных.


Версия Ruby, используемая в этих тестах:

>> RUBY_DESCRIPTION 
=> "ruby 1.8.7 (2010-04-19 patchlevel 253) [i686-darwin10.4.0], MBARI 0x6770, Ruby Enterprise Edition 2010.02"
...