我正在使用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)
所有Ruby 1.9字符串都附加了编码。
YAML将一些非UTF8字符串编码为二进制,即使它们看起来很无辜,也没有任何高位字符。您可能认为您的代码始终使用UTF8,但builtins可以返回非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"
答案 1 :(得分:7)
在版本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
其中一种编码可以解决您的问题=&gt;源代码编码
这是源代码的编码,可以通过在第一行或第二行添加魔术编码字符串来指定(如果源代码的第一行有一个sha-bang字符串) 神奇的编码代码可以是以下之一:
所以在你的情况下,如果你使用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
答案 2 :(得分:0)
我在Windows上使用1.9.3p545一直在努力解决这个问题 - 只是使用包含字符串的简单哈希 - 而且没有Thor。
gem ZAML非常简单地解决了这个问题:
require 'ZAML'
yaml = ZAML.dump(some_hash)
File.write(path_to_yaml_file, yaml)