【问题标题】:UTF-8 ruby encodingUTF-8 红宝石编码
【发布时间】:2016-01-13 21:18:57
【问题描述】:

我有这个字符串:WinterIDäSchwiiz,它来自一个 API,我想在数据库中搜索它。现在事实证明,这个字符串的编码与它在我的数据库中的保存方式不同。然而 ruby​​ 说两者的编码都是 utf-8。怎么回事?

我找到了解决这个问题的最糟糕的方法,方法是深入到字节序列并用不同的字节序列替换代表“ä”的字节,然后将其强制编码为 utf8。它有效,但伤害了我的眼睛。有没有比以下更好的解决方案:

 "WinterIDäSchwiiz".bytes.join(",").gsub("97,204,136","195,164").split(",").collect{|s| s.to_i}.pack('C*').force_encoding('utf-8')

【问题讨论】:

  • 您的问题中没有足够的信息。如果不是 UTF-8,字符串的正确编码是什么? API 的 HTTP 标头报告什么编码?数据库表上设置了什么编码?什么代码负责从 API 中检索数据?什么代码将其插入数据库?什么代码从数据库中检索它?

标签: ruby encoding utf-8


【解决方案1】:

您的字符串是 UTF-8。

我知道,因为您的解决方法是用字节 (195, 164) 替换字节 (97, 204, 136)。

您要替换的第一个字节 97 (0x61) 是 UTF-8 字符 a。后两个字节 204 和 136 (0xCC 0x88) 是 UTF-8 字符 U+0308、combining diaeresis:̈ 的字节。这两个字符组合成

您期望的字节是 195 和 164 (0xC3 0xA4),它们加起来是 U+00E4 或 Latin small letter "a" with diaeresis

两者都是 UTF-8。一个打印,另一个打印ä。这是Unicode equivalence 的示例。

换句话说:

str1 = "a\xCC\x88"
puts str1 # => ä
p str1.bytes # => [97, 204, 136]
p str1.encoding # => #<Encoding:UTF-8>

str2 = "\xC3\xA4"
puts str2 # => ä
p str2.bytes # => [195, 164]
p str2.encoding # => #<Encoding:UTF-8>

幸运的是,我们有 Unicode normalization 来帮助解决这个问题。这是一个的话题,但 TL;DR 的不足之处在于 Unicode 联盟已经规定了标准化上述字符串的标准方法,即如何将 str1 转换为 str2

很遗憾,由于您没有提供任何详细信息,因此无法说出最适合您的解决方案。您的数据库可能具有内置的规范化功能,但我不知道您使用的是什么数据库,所以我不能说。既然您确实提到了 Ruby,我可以为您指出 String#unicode_normalize 方法,该方法是在 Ruby 2.2 的 Ruby 标准库中引入的:

str1 = "a\xCC\x88"
str2 = "\xC3\xA4"
p str1 == str2 # => false

str1_normalized = str1.unicode_normalize

p str1_normalized == str2
# => true
p str1_normalized.bytes == str2.bytes
# => true

如果您没有 Ruby 2.2+,那么……升级。但如果由于某种原因无法升级,您可以使用ActiveSupport::Multibyte::Unicode.normalize,如果您使用的是 Rails,这会特别方便,或者Unicode gem

还有一件事

你不需要这样做,因为上面是在 Ruby 中进行 Unicode 规范化的正确方法,但是更简单的方法:

"WinterIDäSchwiiz".bytes.join(",").gsub("97,204,136","195,164").split(",").collect{|s| s.to_i }.pack('C*').force_encoding('utf-8')

...应该是这样的:

"WinterIDäSchwiiz".gsub("a\xCC\x88", "\xC3\xA4")

任何时候你在 Ruby 中看到类似 join(",")...split(",") 的东西,这几乎肯定是错误的解决方案。

【讨论】:

  • 这是一个很好的答案!非常感谢我学到了很多东西!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多