我从utf-8页面上删除了一个字段:
"O’Reilly"
并保存在yml文件中:
:name: "O\xE2\x80\x99Reilly"
(xE2x80x99是correct UTF-8 representation of this apostrophe)
然而,当我将值加载到哈希并将其输出到标记为utf-8的页面时,我得到:
OâReilly
我查找了字符â,它以UTF-16编码为x00E2,字符x80和x89不可见,但在我粘贴字符串后出现。我认为这意味着我的应用程序输出三个UTF-16字符而不是一个UTF-8。
如何让rails将3字节UTF-8代码解释为单个字符?
答案 0 :(得分:2)
Ruby字符串是字节序列而不是字符:
$ irb
>> "O\xE2\x80\x99Reilly"
=> "O\342\200\231Reilly"
您的字符串是10个字节但8个字符的序列(如您所知)。看到你在HTML中输出正确的字符串最安全的方法(我假设你想要HTML,因为你提到了Rails)是将不可打印的字符转换为HTML实体;在你的情况下
O’Reilly
这需要一些工作,但在以UTF-8发送HTML但最终用户已将其浏览器设置为覆盖并显示Latin-1或其他一些愚蠢的限制字符集的情况下,它应该会有所帮助。
答案 1 :(得分: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'
答案 2 :(得分: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。这有点乱。