4

在 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]?使用新流重新打开与仅使用新流相比有什么优势吗?

4

2 回答 2

1

不久前,我与 IRB 上的一些开发人员进行了交谈,我得到的回应是,它主要用于更改$std变量以修改 where 方法,例如putsprint输出到...

$stdout.reopen(File.open('log'))
puts 'hello world'

使用这个而不是...的原因

$stdout = File.open('log')

......虽然有点悬而未决。我有一位开发人员说直接赋值不能很好地与 ruby​​ 的某些 C 函数配合使用。我对 C 知之甚少,对此不能说太多,但他向我指出了一些minitest 源,以查看它的使用示例。然而,显然,自从开发人员上次查看它以来,甚至源已经切换到直接分配与重新打开。

总之......从外观上看它IO#reopen可能没用,但我很想听到反对这一点的论点。

更新

好的,所以我重新阅读了文档,发现有第二组 opts reopen

reopen(path, mode_str) → ios

reopen(other_IO) → ios与选项相反,这实际上似乎有点有用。

于 2012-12-11T21:57:29.913 回答
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/nullFile 对象不使用 ,而是分配给 时 $stderrstderr_copy将保留其原始输出流。只$stderr得到新的filenostderr_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
于 2021-04-17T04:14:40.853 回答