2012-02-13 25 views
4

我試圖設置$ stdout來臨時寫入文件,然後返回到文件。

test.rb : 
    old_stdout = $stdout  
    $stdout.reopen("mytestfile.out",'w+') 
     puts "this goes in mytestfile" 
    $stdout= old_stdout 
puts "this should be on the console" 
    $stdout.reopen("mytestfile1.out",'w+') 
     puts "this goes in mytestfile1:" 
    $stdout = old_stdout 
puts "this should be back on the console" 

這裏是輸出。

ruby test.rb => no output on the console 
cat mytestfile.out 
    this goes in mytestfile 
    this should be on the console 
cat mytestfile1.out 
    this goes in mytestfile1: 
    this should be back on the console 

我不知道爲什麼$ stdout沒有重置爲控制檯?

+0

我確定有人會喜歡,如果你接受張貼的答案之一,如果這解決了你的問題當然! – user2398029 2012-02-21 02:28:20

回答

6

這個問題可以通過改變前呼籲$stdoutdup解決:

old_stdout = $stdout.dup 
$stdout.reopen("mytestfile.out",'w+') 
puts "this goes in mytestfile" 
$stdout = old_stdout.dup 
puts "this should be on the console" 
$stdout.reopen("mytestfile1.out",'w+') 
puts "this goes in mytestfile1:" 
$stdout = old_stdout 
puts "this should be back on the console" 

輸出:

ruby test.rb 
# => this should be on the console 
# => this should be back on the console 
cat mytestfile.out 
# => this goes in mytestfile 
cat mytestfile1.out 
# => this goes in mytestfile1 

下面是我通常打包這個功能集成到一個功能:

# Runs a block of code while blocking stdout. 
# Note that /dev/null should be changed to NUL on Windows. 
def silence_stdout(log = '/dev/null') 
    old = $stdout.dup 
    $stdout.reopen(File.new(log, 'w')) 
    yield 
    $stdout = old 
end 

用法:

silence_stdout 'mytestfile.out' do 
    puts "this goes in mytestfile" 
end 

puts "this should be on the console" 

silence_stdout 'mytestfile1.out' do 
    puts "this goes in mytestfile1" 
end 

puts "this should be back on the console" 

編輯:另一個海報提到,只有在使用純Ruby代碼時才需要使用reopen。上面的函數既可以使用純Ruby代碼,也可以使用寫入STDOUT的C擴展。

+0

+1,很好的答案。 – 2012-02-13 02:53:36

+0

thnx。這似乎是一個很好的解決方案,但由於某種原因,我在block_given上得到錯誤?在方法!! ruby​​1.8.7。接受答案..假設我的代碼被搞亂了.. – codeObserver 2012-02-22 01:44:14

+0

我只是在這裏釣魚,但你有沒有嘗試明確地將該塊傳遞給函數?例如。 'def silence_stdout(log ='/ dev/null',&block)' – user2398029 2012-02-22 03:39:12

3

如果您只是使用Ruby代碼,則不需要使用reopenputs和其他Ruby方法將使用當前值$stdout,因此您可以重新分配它。

old_stdout = $stdout  
$stdout = File.new("mytestfile.out",'w+') 
puts "this goes in mytestfile" 
$stdout = old_stdout 
puts "this should be on the console" 
$stdout = File.new("mytestfile1.out",'w+') 
puts "this goes in mytestfile1:" 
$stdout = old_stdout 
puts "this should be back on the console" 

你只需要使用reopen,如果你正在做的事情,如創建子進程(例如用fork),並希望孩子的輸出到別處去,或者如果你有一個擴展,它直接寫入到標準輸出,而不全球使用Ruby的$stdout

在你的代碼,當你調用reopen要重定向$stdoutold_stdout,因爲它們都只是同一個IO對象,這就是爲什麼你沒有得到輸出回控制檯時分配的引用old_stdout回到stdout

+0

好的答案,但你不需要old_stdout,你可以使用STDOUT。你也打開了你的文件(寵物狗)。 – pguardiario 2012-02-13 03:06:49

+0

@pguardiario是的,我只是對問題代碼進行了最小更改,以顯示他出錯的地方。這當然不是「生產質量」,但希望更好地瞭解爲什麼原始代碼無法正常工作。 (另外,'$ stdout'可能已經被分配給'STDOUT'以外的東西,因此可能需要使用'old_stdout')。 – matt 2012-02-13 03:11:07

相關問題