了解ruby方法$ stdout的工作原理

时间:2017-01-23 13:56:02

标签: ruby stdout

这是一个简单的ruby脚本,它接受来自用户的输入并提供输出(是的,它将被重构)。我希望这个脚本能够将输出提供给文本文件,而不是控制台窗口。这是通过简单地添加$stdout = File.new('out.txt', 'w')来实现的,但我认为这一行只会描述一个变量,我将在稍后使用它告诉脚本使用它将输出写入创建的文件。

我找不到有关此方法的大量文档,并想知道该程序如何知道如何将生成的输出写入该文件?

3 个答案:

答案 0 :(得分:5)

$stdout是一个全局变量。默认情况下,它存储与程序标准输出(默认情况下为控制台)相关联的IO类型的对象。

putsKernel module的一种实际调用$stdout.send()并将其传递给它的参数列表的方法。正如文档所解释的那样,puts(obj, ...)相当于$stdout.puts(obj, ...)

您的代码将$stdout替换为类File的扩展类IO的对象。创建文件后,您的对象会打开文件out.txt进行编写,并与IO的继承一起使用,它与$stdout的默认行为完全兼容。

由于默认情况下,所有输出都转到$stdout,因此您对$stdout的新定义可确保将输出写入文件out.txt,而无需对代码进行其他更改。

答案 1 :(得分:4)

$stdout是一个全局变量(由$表示),根据文档,puts是:

  

相当于

$stdout.puts(obj, ...)

如果您将另一个对象分配给$stdout,则Kernel#puts只会将puts发送给该对象。同样,print会发送write

class Foo < BasicObject
  def puts(*args)
    ::STDOUT.puts "Foo#puts called with #{args.inspect}"
  end

  def write(*args)
    ::STDOUT.puts "Foo#write called with #{args.inspect}"
  end
end

$stdout = Foo.new

puts 'hello', 'world'
# Foo#puts called with ["hello", "world"]
print "\n"
# Foo#write called with ["\n"]

请注意,如果您分配给$stdout,Ruby会检查对象是否响应write。如果没有,则会引发TypeError

答案 2 :(得分:0)

可能值得强调的是,其他帖子提到的这是一个全局变量,修改它不是线程安全的。例如,如果您将$ stdout指向新的IO流,则应用程序(在该进程线程上)的任何将记录到stdout,现在将记录到新的IO流中。这可能会导致在新IO流中出现多个意外且可能敏感的输入流。