Thor 和 YAML 输出为二进制?



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

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

有什么想法吗?

所有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
=> "--- testn...n"
>> x.force_encoding "ASCII-8BIT"
=> "test"
>> x.to_yaml
=> "--- !binary |-n  dGVzdA==n"

版本1.9.3p125之后,YAML引擎中的ruby构建将以不同于以前的方式处理所有二进制编码。您所需要做的就是在String.to_yaml.之前设置正确的非二进制编码

在Ruby 1.9中,所有String对象都附加了一个Encoding对象正如下面的博客(James Edward Gray II)所提到的,ruby在生成String时内置了三种类型的编码: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

我一直在Windows上使用1.9.3p545——只使用一个包含字符串的简单哈希——而没有Thor。

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

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

最新更新