Конвертировать символы не ASCII из ASCII-8BIT в UTF-8 - PullRequest
44 голосов
/ 02 февраля 2011

Я извлекаю текст с удаленных сайтов и пытаюсь загрузить его в приложение Ruby 1.9 / Rails 3, которое по умолчанию использует utf-8.

Вот пример некоторого оскорбительного текста:

Cancer Res; 71(3); 1-11. ©2011 AACR.\n

Код расширенного авторского права выглядит следующим образом:

Cancer Res; 71(3); 1-11. \xC2\xA92011 AACR.\n

Руби говорит мне, что строка кодируется как ASCII-8BIT, и подача в мое приложение Rails дает мне следующее:

incompatible character encodings: ASCII-8BIT and UTF-8

Я могу удалить код авторского права, используя это регулярное выражение

str.gsub(/[\x00-\x7F]/n,'?')

чтобы произвести это

Cancer Res; 71(3); 1-11. ??2011 AACR.\n

Но как я могу получить символ авторского права (и другие символы, такие как греческие буквы) , преобразованные в те же символы в UTF-8? Конечно, это возможно ...

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

str.force_encoding('utf-8').encode

Я понимаю, что есть много других людей с подобными проблемами, но я еще не нашел решение, которое работает.

Ответы [ 4 ]

63 голосов
/ 02 февраля 2011

Это работает для меня:

#encoding: ASCII-8BIT
str = "\xC2\xA92011 AACR"
p str, str.encoding
#=> "\xC2\xA92011 AACR"
#=> #<Encoding:ASCII-8BIT>

str.force_encoding('UTF-8')
p str, str.encoding
#=> "©2011 AACR"
#=> #<Encoding:UTF-8>
27 голосов
/ 25 сентября 2012

Есть две возможности:

  1. Входные данные уже UTF-8, но Руби просто не знает этого. Это похоже на ваш случай, так как "\ xC2 \ xA9" является допустимым UTF-8 для символа авторского права. В этом случае вам просто нужно сообщить Ruby, что данные уже в формате UTF-8 с использованием force_encoding.

    Например, "\ xC2 \ xA9" .force_encoding ('ASCII-8BIT') воссоздает соответствующий бит ваших входных данных. И "\ xC2 \ xA9" .force_encoding ('ASCII-8BIT'). Force_encoding ('UTF-8') продемонстрирует, что вы можете сказать Ruby, что это действительно UTF-8, и получить желаемый результат.

  2. Входные данные находятся в другой кодировке, и вам нужен Ruby для перекодирования в UTF-8. В этом случае вам нужно будет указать Ruby текущую кодировку (ASCII-8BIT является бинарным языком для двоичного кода, это не настоящая кодировка), а затем указать Ruby перекодировать его.

    Например, скажем, ваши входные данные были ISO-8859-1. В этой кодировке символом авторского права является просто "\ xA9". Это сгенерирует такой бит данных: "\ xA9" .force_encoding ('ISO-8859-1') И это продемонстрирует, что вы можете заставить Ruby перекодировать это в UTF-8: "\ xA9" .force_encoding ('ISO -8859-1 '). закодировать (' UTF-8' )

6 голосов
/ 21 сентября 2011

Раньше я делал это для скрипта, который очищал греческие Windows-закодированные страницы, используя open-uri, iconv и Hpricot:

doc = open(DATA_URL)
doc.rewind
data = Hpricot(Iconv.conv('utf-8', "WINDOWS-1253", doc.readlines.join("\n")))

Я полагаю, что это был Ruby 1.8.7, не знаю, как делас рубином 1.9

1 голос
/ 19 декабря 2018

У меня были проблемы с кодировкой символов, и другие ответы были полезны, но не работали для каждого случая. Вот решение, которое я придумала, с помощью кодирования сил, когда это возможно, и транскодирования с использованием «?», Когда это невозможно. Вот решение:

  def encode str
    encoded = str.force_encoding('UTF-8')
    unless encoded.valid_encoding?
      encoded = str.encode("utf-8", invalid: :replace, undef: :replace, replace: '?')
    end
    encoded
  end

force_encoding работает большую часть времени, но я сталкивался с некоторыми строками, где это терпит неудачу. В таких строках будут заменены недопустимые символы:

 str = "don't panic: \xD3"
 str.valid_encoding?
 false
 str = str.encode("utf-8", invalid: :replace, undef: :replace, replace: '?')
 "don't panic: ?"
 str.valid_encoding?
 true

Обновление: у меня были некоторые проблемы в работе с приведенным выше кодом. Я рекомендую вам настроить модульные тесты с известным текстом проблемы, чтобы убедиться, что этот код работает для вас так, как вам нужно. Как только я приду к версии 2, я обновлю этот ответ.

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