【问题标题】:Reopening an IO Stream vs. just using the new Stream重新打开 IO 流与仅使用新流
【发布时间】:2012-11-16 23:27:46
【问题描述】:

在 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.closef1.readlines[0] 时,为什么要重新打开 f2?与仅使用新流相比,使用新流重新打开有什么优势?

【问题讨论】:

    标签: ruby io


    【解决方案1】:

    我怀疑主要区别在于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 文件对象分配给 $stderr 时,stderr_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
    

    【讨论】:

      【解决方案2】:

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

      $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 选项相比,这实际上似乎有些用处。

      【讨论】:

        猜你喜欢
        • 2011-10-04
        • 1970-01-01
        • 2014-03-13
        • 2012-10-30
        • 1970-01-01
        • 2016-12-12
        • 2019-09-02
        • 2020-03-20
        • 1970-01-01
        相关资源
        最近更新 更多