1

我有一个从 utf-8 页面抓取的字段:

"O’Reilly"

并保存在 yml 文件中:

:name: "O\xE2\x80\x99Reilly"

(xE2x80x99 是这个撇号的正确 UTF-8 表示

但是,当我将值加载到哈希中并将其生成到标记为 utf-8 的页面时,我得到:

OâReilly

我查找了字符 â,它以 UTF-16 编码为 x00E2,当我粘贴字符串时,字符 x80 和 x89 是不可见的,但在 â 之后出现。我认为这意味着我的应用程序正在输出三个 UTF-16 字符而不是一个 UTF-8。

如何让 Rails 将 3 字节 UTF-8 代码解释为单个字符?

4

3 回答 3

2

Ruby 字符串是字节序列而不是字符:

$ irb
>> "O\xE2\x80\x99Reilly"
=> "O\342\200\231Reilly"

您的字符串是 10 个字节但 8 个字符的序列(如您所知)。看到您在 HTML 中输出正确字符串的最安全方法(我假设您想要 HTML,因为您提到了 Rails)是将不可打印的字符转换为 HTML 实体;在你的情况下

O’Reilly

这需要一些工作,但在以 UTF-8 发送 HTML 但最终用户已将其浏览器设置为覆盖并显示 Latin-1 或其他一些愚蠢的受限字符集的情况下,它应该会有所帮助。

于 2011-07-07T20:03:59.027 回答
2

最终,这是由于使用 psych(在 rails 中)加载 syck 文件(由外部脚本生成)引起的。用 syck 加载解决了这个问题:

#in ruby environment
puts YAML::ENGINE.yamler => syck

#in rails
puts YAML::ENGINE.yamler => psych

#in webapp
YAML::ENGINE.yamler = 'syck'
a = YAML::load(file_saved_with_syck)
a[index][:name] => "O’Reilly"
YAML::ENGINE.yamler = 'psych'
于 2011-07-08T21:18:42.073 回答
1

我认为这意味着我的应用程序正在输出三个 UTF-16 字符而不是一个 UTF-8。

它不是真正的 UTF-16,它在网络上很少使用(并且在很大程度上中断了)。您的应用正在输出三个 Unicode 字符(包括两个不可见的控制代码),但这与 UTF-16 编码不同。

问题似乎是 YAML 文件被读入就好像它是 ISO-8859-1 编码的一样,因此\xE2字节映射到字符 U+00E2 等等。我猜您正在使用 Ruby 1.9,并且 YAML 被解析为具有关联的 ASCII-8BIT 编码而不是 UTF-8 的字节字符串,导致字符串稍后经历一轮转码(修改)。

如果是这种情况,您可能必须将force_encoding字符串读回应有的状态,或者设置default_internal为将字符串读回 UTF-8。这个有点乱

于 2011-07-07T23:52:50.887 回答