如何通过 Ruby 或 Rails 检查字符集是否使用 UTF-8 编码?
对于大多数多字节编码,可以通过编程方式检测无效的字节序列。由于 Ruby 默认将所有字符串视为 UTF-8
,因此您可以检查字符串是否是有效的 UTF-8
:
# encoding: UTF-8
# -------------------------------------------
str = "Partly valid\xE4 UTF-8 encoding: äöüß"
str.valid_encoding?
# => false
str.scrub('').valid_encoding?
# => true
如果一个字符串不是有效的 UTF-8
编码,但你知道实际的字符编码,你可以将该字符串转换为 UTF-8
编码。
示例
有时候,您会遇到这样的情况:您知道输入文件的编码是 UTF-8
或者 CP1252
(也称为 Windows-1252
)之一。
检查它的编码并将其转换为 UTF-8(如果需要):
# encoding: UTF-8
# ------------------------------------------------------
test = "String in CP1252 encoding: \xE4\xF6\xFC\xDF"
File.open( 'input_file', 'w' ) {|f| f.write(test)}
str = File.read( 'input_file' )
unless str.valid_encoding?
str.encode!( 'UTF-8', 'CP1252', invalid: :replace, undef: :replace, replace: '?' )
end #unless
# => "String CP1252 encoding: äöüß"
=======
注释
通过编程,可以以相当高的可靠性检测大多数多字节编码,如UTF-8(在Ruby中,请参考:#valid_encoding?)。仅经过16个字节后,随机的字节序列成为有效UTF-8的概率仅为0.01%。(与依赖于UTF-8 BOM进行比较)
然而,编程检测(无效)单字节编码,如CP1252
或ISO-8859-1
并不容易。因此,上述代码片段不能反向工作,即无法检测 CP1252
编码字符串是否有效。
尽管UTF-8已成为Web中默认编码越来越受欢迎,但 CP1252
和其他 Latin1
变体仍然在西方国家特别是北美非常流行。请注意,还有一些非常相似但略有不同于 CP1252
(也称为 Windows-1252
)的单字节编码。例如: ISO-8859-1
, ISO-8859-15
UTF-8
编码。您可以通过在采用UTF-8
编码的字符串str
上调用str.valid_encoding?
来实现。我的回答没有表达清楚吗? - Andreas Rayo KniepCP1252
这样的单字节编码字符串的无效性。但是,你可以相当可靠地(取决于字符串的长度)检查多字节编码字符串(如UTF-8
)的无效性。 - Andreas Rayo Kniep在 Ruby 或任何地方,没有确切的方法来做到这一点:
str = 'foo' # start with a simple string
# => "foo"
str.encoding
# => #<Encoding:UTF-8> # which is UTF-8 encoded
str.bytes.to_a
# => [102, 111, 111] # as you can see, it consists of three bytes 102, 111 and 111
str.encode!('us-ascii') # now we will recode the string to 8-bit us-ascii encoding
# => "foo"
str.encoding
# => #<Encoding:US-ASCII>
str.bytes.to_a
# => [102, 111, 111] # see, same three bytes
str.encode!('windows-1251') # let us try some cyrillic
# => "foo"
str.encoding
# => #<Encoding:Windows-1251>
str.bytes.to_a
# => [102, 111, 111] # see, the same three again!
当然,你可以对文本进行一些统计分析,并消除文本无效的编码,但从理论上讲,这是一个不可解决的问题。valid_encoding?
检查字符串是否包含无效的字节序列。它并不表示该(本来有效的)字节序列来自于某种编码,我认为这就是问题所在。 - Mladen JablanovićUTF-8
:仅仅16个字节后,随机字节序列被确认为有效的UTF-8
的概率只有0.01%。 因此,str.valid_encoding?
算法在确定给定的字符串是否为UTF-8
编码方面是相当可靠的。 - Andreas Rayo Kniep"your string".encoding
# => #<Encoding:UTF-8>
或者如果你想要以编程方式实现,
"your string".encoding.name == "UTF-8"
# => true