Преобразование не-ASCII символы из ASCII-8bit в UTF-8

Обновить

December 2018

Просмотры

58k раз

39

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

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

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

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

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

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

3 ответы

56

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

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

Я использовал, чтобы сделать это для сценария, который Царапины греческого Windows, закодированные страниц, используя открытый Ури, Iconv и Hpricot:

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

Я считаю, что Руби 1.8.7, не знаю, как обстоят дела с рубином 1.9

26

Есть два варианта:

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

    Например, «\ xc2 \ xÀ9» .force_encoding ( «ASCII-8bit») будет воссоздать соответствующий бит входных данных. И "\ xc2 \ xÀ9" .force_encoding ( 'ASCII-8bit'). Force_encoding ( 'UTF-8') будет продемонстрировать, что вы можете сказать Руби, что это действительно UTF-8 и получить желаемый результат.

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

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