【问题标题】:Thor & YAML outputting as binary?Thor & YAML 输出为二进制?
【发布时间】:2012-03-21 23:04:51
【问题描述】:

我正在使用 Thor 并尝试将 YAML 输出到文件。在 irb 中,我得到了我的期望。 YAML 格式的纯文本。但是当 Thor 中某个方法的一部分时,它的输出就不同了……

class Foo < Thor
  include Thor::Actions

  desc "bar", "test"
  def set
    test = {"name" => "Xavier", "age" => 30}
    puts test
    # {"name"=>"Xavier", "age"=>30}
    puts test.to_yaml
    # !binary "bmFtZQ==": !binary |-
    #   WGF2aWVy
    # !binary "YWdl": 30
    File.open("data/config.yml", "w") {|f| f.write(test.to_yaml) }
  end
end

有什么想法吗?

【问题讨论】:

  • 我刚刚运行了您的示例,它给了我非常好的输出。我跑雷神 0.14.6。
  • 感谢您抽出宝贵时间查看。在这一点上,我不知道该怎么做。如果这有什么不同的话,我正在使用 Ruby 1.9.3p125。 :)
  • 我安装了 1.9.3 并再次运行它,确实是二进制输出。我注意到 YAML 在安装过程中得到了升级。它可能与升级版本有关。
  • 谢谢马兰。我假设 yaml 是内置在 ruby​​ 中的,rvm 安装 1.9.2 而不是安装 1.9.3 w/yaml 的降级版本会更容易吗?
  • 是的,一旦我发出 rvm 1.9.2 一切都会再次运行,yaml 明智。如果您不需要需要 1.9.3,我会切换回1.9.2

标签: ruby yaml thor


【解决方案1】:

所有 Ruby 1.9 字符串都附加了编码。

YAML 将一些非 UTF8 字符串编码为二进制,即使它们看起来很无辜,也没有任何高位字符。您可能认为您的代码始终使用 UTF8,但内置函数可以返回非 UTF8 字符串(例如文件路径例程)。

为避免二进制编码,请在调用 to_yaml 之前确保所有字符串编码均为 UTF-8。使用 force_encoding("UTF-8") 方法更改编码。

例如,这就是我将选项哈希编码为 yaml 的方式:

options = {
    :port => 26000,
    :rackup => File.expand_path(File.join(File.dirname(__FILE__), "../sveg.rb"))
}
utf8_options = {}
options.each_pair { |k,v| utf8_options[k] = ((v.is_a? String) ? v.force_encoding("UTF-8") : v)}
puts utf8_options.to_yaml

这里是 yaml 将简单字符串编码为二进制的示例

>> x = "test"
=> "test"
>> x.encoding
=> #<Encoding:UTF-8>
>> x.to_yaml
=> "--- test\n...\n"
>> x.force_encoding "ASCII-8BIT"
=> "test"
>> x.to_yaml
=> "--- !binary |-\n  dGVzdA==\n"

【讨论】:

    【解决方案2】:

    在 1.9.3p125 版本之后,ruby 内置 YAML 引擎将对所有 BINARY 编码进行不同于以前的处理。您需要做的就是在 String.to_yaml 之前设置正确的非 BINARY 编码。

    在 Ruby 1.9 中,所有 String 对象都附加了一个 Encoding 对象 并且正如以下博客(由 James Edward Gray II 撰写)所提到的,当 String 生成时,ruby 内置了三种类型的编码: http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings.

    一种编码可以解决你的问题 => 源代码编码

    这是您的源代码的编码,可以通过在第一行或第二行添加魔术编码字符串来指定(如果您在源代码的第一行有一个 sha-bang 字符串) 魔术编码代码可以是以下之一:

    • #编码:utf-8
    • #编码:utf-8
    • # -- 编码:utf-8 --

    所以在你的情况下,如果你使用 ruby​​ 1.9.3p125 或更高版本,这应该通过在代码开头添加一个魔法编码来解决。

    # encoding: utf-8
    require 'thor'
    class Foo < Thor
      include Thor::Actions
    
      desc "bar", "test"
      def bar
        test = {"name" => "Xavier", "age" => 30}
        puts test
        #{"name"=>"Xavier", "age"=>30}
        puts test["name"].encoding.name
        #UTF-8
        puts test.to_yaml
        #---
        #name: Xavier
        #age: 30
        puts test.to_yaml.encoding.name
        #UTF-8
      end
    end
    

    【讨论】:

      【解决方案3】:

      我一直在努力解决这个问题,在 Windows 上使用 1.9.3p545 - 仅使用包含字符串的简单哈希 - 而没有 Thor。

      gem ZAML 很简单地解决了这个问题:

      require 'ZAML'
      yaml = ZAML.dump(some_hash)
      File.write(path_to_yaml_file, yaml)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-14
        • 1970-01-01
        • 1970-01-01
        • 2014-03-13
        • 2017-12-21
        • 1970-01-01
        • 2011-06-10
        • 2017-11-29
        相关资源
        最近更新 更多