Ответ 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>
Я вынимаю текст с удаленных сайтов и пытаюсь загрузить его в приложение 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
Я понимаю, что есть много других людей с подобными проблемами, но мне еще предстоит увидеть решение, которое работает.
Это работает для меня:
#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>
Есть две возможности:
Входные данные уже 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' )
Я использовал это для 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
У меня были проблемы с кодировкой символов, и другие ответы были полезны, но не работали для каждого случая. Вот решение, которое я придумал, с помощью которого по возможности кодирует силы и транскодирует с помощью '? когда это невозможно. Вот решение:
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