I suspect that the main difference is that with reopen
, the new stream would apply not only to subsequent uses of the $std...
variable, but also to variables that previously were assigned the value of the $std...
variable. This can be good or bad, depending on your situation.
This irb session shows that with reopen
, a variable that was assigned previous to the stream change will acquire the newly changed stream. Note that the fileno
does not change for either variable, and both variables produce no output:
> $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
In contrast, when instead of using reopen
, the newly opened /dev/null
File object is assigned to $stderr
, stderr_copy
will retain its original output stream. Only $stderr
gets the new fileno
, and stderr_copy
still produces output:
> $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
If you want to use reopen
, but want to save a copy of the original output stream, you can use 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