Как прочитать текстовый файл ANSI и преобразовать строки в UTF-8 в Ruby 1.9? - PullRequest
2 голосов
/ 12 мая 2011

Я пытаюсь читать текстовые файлы с помощью Ruby 1.9 и конвертировать их в свою собственную структуру XML. У меня нет контроля над исходным текстовым файлом, поэтому они могут быть в любой кодировке.

Вот что я делаю в данный момент:

lines = File.readlines(input_file)
lines.each do |line|
  #do something
end

У меня проблема с файлом, который содержит символ é (xE9). Когда я пытаюсь обработать соответствующую строку, я получаю исключение Invalid byte sequence in UTF-8, когда я вызываю .match(...) в строке.

Я попытался использовать обходной путь, описанный в Исправление неверного UTF-8 в Ruby, пересмотрено

lines = File.readlines(input_file)
ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
lines.each do |line|
  unless line.empty?
   valid_string = ic.iconv(line + ' ')[0..-2]
   #do something
  end
end

но это просто удаляет символ é из строки, что не то, что я хочу.

Я думаю, что реальная проблема заключается в том, что сам файл, похоже, не находится в UTF-8, а использует некоторую кодировку ANSI. Хотя файл не является UTF-8, результирующий строковый объект сообщает, что это UTF-8 при вызове .encoding; Я предполагаю, что мне нужно использовать другой способ чтения файла, чтобы он работал как для файлов ANSI, так и для файлов UTF-8, но я новичок в Ruby и действительно не знаю, с чего начать.

Ответы [ 2 ]

3 голосов
/ 12 мая 2011

Символ является частью наборов символов ISO-8859-1 и Win-1252, среди которых другие . Второй, вероятно, самый популярный набор символов для Windows и ваш наиболее вероятный источник.

RUBY_VERSION # => "1.9.2"

Это моя версия Ruby, в которой выполняются следующие тесты. Обратите внимание, что в следующих примерах строки # encoding не являются комментариями, они представляют собой директивы для Ruby, для которых используется набор символов при обнаружении незакодированных двоичных символов:

# encoding: Windows-1252

RUBY_VERSION # => "1.9.2"

asdf = "\xe9"
asdf.encoding # => #<Encoding:Windows-1252>
asdf.encode('UTF-8') # => "é"
asdf.encode('UTF-8').encoding # => #<Encoding:UTF-8>

Показывает символ в ISO-8859-1:

# encoding: ISO-8859-1

RUBY_VERSION # => "1.9.2"

asdf = "\xe9"
asdf.encoding # => #<Encoding:ISO-8859-1>
asdf.encode('UTF-8') # => "é"
asdf.encode('UTF-8').encoding # => #<Encoding:UTF-8>

Джеймс Грей сделал серию статей пару лет назад о работе с этим материалом. Это хорошее чтение.

Теперь вернемся к попытке выяснить, в каком наборе символов может находиться символ: если у вас есть только один символ, поскольку он может быть в нескольких наборах одновременно, трудно определить, какой это набор. Если у вас есть больше символов> = "\ x80", вы можете запустить поддержку наборов символов iconv и попытаться преобразовать их. Это грязно, но я должен был сделать это в Perl из-за скрипа около пяти лет назад. Альтернативой является использование кода Python chardet.

В статьях Джеймса Грея есть ссылка на статью, в которой рекомендуется rchardet.

В вышеприведенных процедурах упоминаются детекторы кодировки Mozilla, которые дадут вам больше информации о том, как с этим справиться.

2 голосов
/ 12 мая 2011

вы можете попробовать это на консоли, это может быть подсказка:

Я делаю это с помощью системной команды, подобной этой:

iconv -f windows-1252 -t UTF-8 "#{csv_file}" > #{Rails.root}/tmp/Kdvakanz-utf8.csv

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...