在Ruby-Docs中,它提供了以下示例:
f1 = File.new("testfile")
f2 = File.new("testfile")
f2.readlines[0] #=> "This is line one\n"
f2.reopen(f1) #=> #<File:testfile>
f2.readlines[0] #=> "This is line one\n"
我的问题是,为什么只能f2
和f2.close
重新开启f1.readlines[0]
?使用新流重新打开是否有任何优势?仅使用新流?
答案 0 :(得分:1)
我在一段时间之前与IRB上的一些开发人员交谈,我得到的回应是它主要用于更改$std
变量以修改puts
和print
等方法的位置输出到......
$stdout.reopen(File.open('log'))
puts 'hello world'
使用此而不是......的原因
$stdout = File.open('log')
......虽然有点在空中。我有一个开发人员说直接分配并不适合某些ruby的C函数。我不太了解C并且不能对此有太多的了解,但是他向我指了一些minitest source来看一个使用它的例子。然而,显然即使是源码已经切换到直接分配与重新开放,因为开发人员最后一次查看它。
总之......从它的外观来看IO#reopen
可能毫无用处,但我很乐意听到反对的论点。
<强>更新强>
好的,所以我重读了文档,发现reopen
还有第二组选项:
reopen(path, mode_str) → ios
这实际上似乎有点有用,而不是reopen(other_IO) → ios
选项。
答案 1 :(得分:0)
我怀疑主要区别在于 reopen
的新流不仅适用于 $std...
变量的后续使用,还适用于以前被分配了 $std...
变量的值。这可能是好是坏,具体取决于您的情况。
这个 irb 会话表明,对于 reopen
,在流更改之前分配的变量将获取新更改的流。请注意,两个变量的 fileno
都不会改变,并且两个变量都不会产生输出:
> $stderr.fileno
=> 2
> stderr_copy = $stderr
=> #<IO:<STDERR>>
> stderr_copy.fileno
=> 2
> $stderr.reopen(File.open('/dev/null', 'w'))
=> #<File:/dev/null>
> stderr_copy.fileno
=> 2
> $stderr.fileno
=> 2
> $stderr.puts 'foo'
=> nil
> stderr_copy.puts 'foo'
=> nil
相反,当不使用 reopen
时,新打开的 /dev/null
File 对象被分配给 $stderr
,stderr_copy
将保留其原始输出流。只有 $stderr
获得新的 fileno
,而 stderr_copy
仍然产生输出:
> $stderr.fileno
=> 2
> stderr_copy = $stderr
=> #<IO:<STDERR>>
> stderr_copy.fileno
=> 2
> $stderr = File.open('/dev/null', 'w')
=> #<File:/dev/null>
> $stderr.fileno
=> 10
> stderr_copy.fileno
=> 2
> $stderr.puts 'foo'
=> nil
> stderr_copy.puts 'foo'
foo
=> nil
如果您想使用reopen
,但想保存原始输出流的副本,您可以使用dup
:
> stderr_dup = $stderr.dup
=> #<IO:<STDERR>>
> stderr_dup.fileno
=> 10
> $stderr.reopen(File.open('/dev/null', 'w'))
=> #<File:/dev/null>
> $stderr.fileno
=> 2
> stderr_dup.puts 'foo'
foo
=> nil
> $stderr.puts 'foo'
=> nil