【问题标题】:Ruby 1.9, YAML, and string encodings: how to lead a life of sanity?Ruby 1.9、YAML 和字符串编码:如何过上理智的生活?
【发布时间】:2010-01-01 19:20:14
【问题描述】:

在我看来,ruby 1.9 附带的 YAML 库是编码聋的。

这意味着在生成 YAML 时,它将采用任何字节串,并转义任何不输出干净 ASCII 的字节序列。这很蹩脚,但可以接受。

我的问题正好相反。从所述 YAML 转储加载内容时。

在下面的示例中,我创建了一个 UTF-8 字符串,转储它,它的转储类型为 !binary。当我重新加载它时,它的编码为 ASCII-8BIT。在示例的最后,我尝试将原始字符串和重新加载的字符串与另一个 UTF-8 字符串连接起来。后者将失败并返回 Encoding::CompatibilityError。

require 'yaml'
s0 = "Iñtërnâtiônàlizætiøn"
y  = s0.to_yaml
s1 = YAML::load y
puts s0                 # => Iñtërnâtiônàlizætiøn
puts s0.encoding        # => UTF-8
puts s1                 # => Iñtërnâtiônàlizætiøn
puts s1.encoding        # => ASCII-8BIT
puts y                  # => --- !binary |
                        #    ScOxdMOrcm7DonRpw7Ruw6BsaXrDpnRpw7hu
puts "ñårƒ" + s0        # => ñårƒIñtërnâtiônàlizætiøn
puts "ñårƒ" + s1        # => Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT

我认为,当您处理一些包含嵌套散列和带有叶字符串的数组的 YAML 源时,这将如何迅速导致问题很明显。

目前我有一些代码可以遍历所有哈希和数组,并在每个字符串上调用force_encoding。至少可以说,那是难看的。

我现在正在寻找的是一种告诉YAML::load 输入的任何字符串都应被视为并因此将其编码设置为 UTF-8 的方法。 p>


理想情况下,ruby 的 YAML 应该只用正确的编码注释它转储的字符串。有一个 Ya2YAML 项目试图转储 UTF-8 安全 YAML。我不确定它有多远。如果有人玩过它,我欢迎任何想法。

不管怎样,我仍然有这些转储,没有任何编码信息需要处理。虽然我知道它们都是 UTF-8。

【问题讨论】:

  • 重金属变音符号+1。
  • 我刚刚遇到了同样的错误/行为......您是否找到了其他解决方案,或者您仍然只是在执行 YAML.load 然后对每个字符串执行 force_encoding('utf-8') ?跨度>

标签: ruby string encoding yaml ruby-1.9


【解决方案1】:

考虑将您的 ruby​​ 升级到最新的 1.9.2。

我在 1.9.1 中发现了该错误,但在 1.9.2 中没有。

【讨论】:

    【解决方案2】:
    YAML::ENGINE.yamler='psych'
    'Résumé'.to_yaml # => "--- Résumé\n...\n"
    

    【讨论】:

      【解决方案3】:

      首先,您尝试读取的文本文件必须是 UTF-8 编码的(这应该是您的 YAML 文件)。

      然后将此行添加到您的 ruby​​ 文件的顶部,哈希和所有

      # encoding: UTF-8
      

      这意味着所有字符串的默认编码将是 UTF-8,并且应该意味着您使用 YAML.dump('text') 转储的任何文本甚至字符串文字“like this”也应该编码为 UTF- 8,从现在开始一切都应该很好。

      【讨论】:

      • 没关系。从 yaml 中读取为 !binary 的内容最终为 ASCII-8BIT,这可能是出于明显和理智的原因,但因此 yaml 应该正确转储未转义的 UTF8 字符串。我或多或少有一个解决方案,但涉及一个很好的块代码。准备好宝石后,我会发布答案。
      【解决方案4】:

      Evgeny 的答案对我来说仍然显示二进制,但这有效('syck' instoad of 'psych'):

      YAML::ENGINE.yamler='syck'
      'Résumé'.to_yaml # => "--- "R\xE9sum\xE9"
      

      我使用的是 Ruby 1.9。请注意,出于我的目的,对特价商品进行转义很好 - 我只需要它不显示 !binary... 对于普通单词。感谢上帝 .to_yaml 再次对我有用 - 曾经一直使用它。如何真正加载理智的生活:)

      【讨论】:

      • 感谢 user1262147 的修复 - yamler='psych' 对我没有任何帮助,但 yamler='syck' 修复了它。以前 to_yaml 将所有内容都转储为 !binary=whatever - 甚至是来自 UTF8 mysql 表的 ActiveRecord 的属性名称。
      • 答案已过时,制作时已过时,syck 已过时
      猜你喜欢
      • 2012-07-07
      • 2011-07-20
      • 2011-03-10
      • 1970-01-01
      • 2011-01-06
      • 1970-01-01
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      相关资源
      最近更新 更多