将任何编码的字符串强制转换为UTF-8

51

我正在开发一款基于Rails框架的应用程序,其中需要使用来自世界各地的RSS源,但有些源链接并不是UTF-8格式。原始的链接格式我无法控制,为了在应用程序的其他部分中使用它们,这些链接需要转换为UTF-8格式。

我应该如何检测链接的编码并将其转换为UTF-8格式?


要检测编码,您需要解析文档的附带元信息,即HTTP标头或<meta>标签。 - deceze
4个回答

71

Ruby 1.9

“强制”编码很容易,但它不会转换字符,只是改变编码:

str = str.force_encoding('UTF-8')

str.encoding.name # => 'UTF-8'

如果您想进行转换,请使用encode

begin
  str.encode("UTF-8")
rescue Encoding::UndefinedConversionError
  # ...
end

我一定会阅读以下文章以获取更多信息:
http://graysoftinc.com/character-encodings/ruby-19s-string


不起作用: whois = whois.force_encoding("UTF-8") \n whois.encoding.name => "UTF-8" \n whois.scan(/role:\s+(.+)/i) -- 抛出:ArgumentError: invalid byte sequence in UTF-8 - Hackeron
如上所述,force_encoding 不会转换字符,当然也不能神奇地解释无效的 UTF-8 字节序列。 - kwarrick
Ruby 2.2.0及以上版本的当前语法为:str.force_encoding(Encoding::UTF_8)编码 - Joseworks

42
这将确保您拥有正确的编码,并且不会因为替换任何无效或未定义的字符而出错,而是将其替换为空字符串。
这将确保无论如何,您都拥有一个有效的UTF-8字符串。
str.encode(Encoding.find('UTF-8'), {invalid: :replace, undef: :replace, replace: ''})

对于 Ruby 3.0+ 版本:
str.encode(Encoding.find('UTF-8'), invalid: :replace, undef: :replace, replace: '')

3
这将在现代 Ruby(可能是 3.0 之后)引发“无法将哈希隐式转换为字符串”的错误。使用 str.encode(Encoding.find('UTF-8'), invalid: :replace, undef: :replace, replace: '') - ShockwaveNN
1
谢谢,我有这个问题,你的解决方案解决了 Ruby 3+ 的问题 ;) - Matrix

5

只有这个解决方案适用于我:

string.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')

请注意 二进制 参数。

4

Iconv

require 'iconv'
i = Iconv.new('UTF-8','LATIN1')
a_with_hat = i.iconv("\xc2")

总结:iconv宝石负责进行编码转换的所有工作。请确保已安装该宝石:

gem install iconv

现在,您需要知道您的字符串当前使用的编码方式是什么,因为Ruby 1.8将字符串视为一个字节数组(没有固有的编码方式)。例如,假设您的字符串使用的是latin1编码,并且您想将其转换为utf-8编码。

require 'iconv'

string_in_utf8_encoding = Iconv.conv("UTF8", "LATIN1", string_in_latin1_encoding)

谢谢您的回答,但在我的情况下,源数据不一致,我没有可靠的方法来预测编码。 - Hayk Saakian
6
Iconv 不应再被使用。(已弃用)https://dev59.com/JGsz5IYBdhLWcg3wCDl2 - basgys

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接