Подтвердить что ты не робот

Преобразование символов, отличных от ASCII, из ASCII-8BIT в UTF-8

Я вынимаю текст с удаленных сайтов и пытаюсь загрузить его в приложение 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

Ruby сообщает мне, что строка кодируется как 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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

  • Входные данные уже UTF-8, но Ruby просто этого не знает. Это похоже на ваш случай, так как "\ 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 и получить желаемый результат.

    /li >
  • Входные данные находятся в некотором другом кодировании, и вам нужно, чтобы 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' )

Ответ 3

Я использовал это для script, который очищал греческие страницы с кодировкой 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, не уверен, что происходит с ruby ​​1.9

Ответ 4

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

  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