【问题标题】:Difference between reassignment and reopen with Ruby IO streams使用 Ruby IO 流重新分配和重新打开之间的区别
【发布时间】:2011-10-04 17:29:41
【问题描述】:

在 Ruby 中,重新分配 IO 流和使用 IO#reopen 方法有什么区别?换句话说,有什么区别

$stdout = newfile

和:

$stdout.reopen(newfile)

【问题讨论】:

    标签: ruby io stdout variable-assignment


    【解决方案1】:

    我相信在后一种 (reopen) 的情况下,之前的 IO 被刷新并关闭。

    添加:比较输出:

    $stdout.write("Buffered")
    $stdout = $stderr
    $stdout.write("After assignment")
    

    $stdout.write("Buffered")
    $stdout.reopen($stderr)
    $stdout.write("After reopen")
    

    (比较的最佳方法是使用管道重定向输出)

    【讨论】:

      【解决方案2】:

      所以基本上重新打开会将$stdoutnewfile 流相关联=> $stdoutnewfile 将是与同一流相关联的两个文件实例。

      = 实际上会将newfile 文件实例分配给$stdout => $stdoutnewfile 将是指向同一个文件实例的两个变量。

      后果:

      使用reopen 时,实例上的任何更改(不影响流本身)都不会反映在其他实例中。

      = 示例:

      a = File.new('name')
      b = File.new('name')
      
      a.lineno #=> 0
      b.lineno #=> 0
      
      a.lineno = 3
      
      a.lineno #=> 3
      b.lineno #=> 0
      
      b = a 
      
      a.lineno #=> 3
      b.lineno #=> 3
      
      a.lineno = 0
      
      a.lineno #=> 0
      b.lineno #=> 0
      

      reopen 示例:

      a = File.new('name')
      b = File.new('name')
      
      a.lineno #=> 0
      b.lineno #=> 0
      
      a.lineno = 3
      
      a.lineno #=> 3
      b.lineno #=> 0
      
      b.reopen(a)
      
      a.lineno #=> 3
      b.lineno #=> 3
      
      a.lineno = 0
      
      a.lineno #=> 0
      b.lineno #=> 3
      

      【讨论】:

      • 作为后续,sync 选项如何与这两种流重定向方式一起使用?
      • @jrdioko 每次您在File 实例上调用 write 方法时,sync 只会写入文件。 reopen= 都将sync 值“复制”到目标File 实例。切入正题:使用=,您将在两个变量中处理相同的File,因此每次写入两者中的任何一个时,流指针都会在两者上更新。使用reopen 可以让您写入其中一个而不修改另一个位置,因此,如果您再写入另一个,您最终将覆盖之前的内容。
      【解决方案3】:

      当您运行子进程时,区别很重要。

      作业:

      $stdout = File.open("/dev/null", "w")
      system "ls"
      warn $stdout.fileno  # file descriptor number
      

      输出 - 注意system 的输出仍然出现:

      1.txt 2.txt
      7
      

      重新开放:

      $stdout.reopen("/dev/null")
      system "ls"
      warn $stdout.fileno
      

      输出 - system 输出已发送到 /dev/null

      1
      

      总结:

      $stdout$stdin$stderr 的重新分配仅影响当前的 ruby​​ 进程。子进程会将自己的标准输出写入文件描述符 (FD) 1,从 FD 0 读取标准输入,并将诊断输出写入 FD 2。

      如果您希望孩子继承更改,则需要重新打开流,因为这会重用文件描述符。请注意,只有在您 reopen 开始孩子之前,孩子才会受到影响。

      一个用例:您正在编写一个守护程序脚本(或其他需要在您注销后继续运行的脚本)。最佳做法是将所有 3 个标准流重新打开到 /dev/null,否则如果脚本或子进程尝试使用这些流,您可能会遇到管道损坏。

      【讨论】:

        猜你喜欢
        • 2012-11-16
        • 1970-01-01
        • 2019-10-11
        • 1970-01-01
        • 2018-01-16
        • 2014-10-31
        • 2019-08-26
        • 2013-02-14
        • 1970-01-01
        相关资源
        最近更新 更多