STDOUT and $stdout

hi folks

I’ve been using for Ruby for a bit now, but I’ve never felt happy that I’ve
understood the difference purposes of $stdout and STDOUT (and -in & -err).

In particular, I’m interested in doing things similar to what I did in Perl
with select and tie-ing STD filehandles to classes temporarily then
returning to program default values. I’ve seen an interesting example of a
string-based class implementing IO-like behaviour in ‘The Ruby Way’
(223-225), but I’m not sure how to manipulate Ruby’s STDOUT and $stdout to
do useful things with these sort of classes (using .reopen()?), so I’d
appreciate pointers to threads or example code.

Best wishes
alex

alex fenton

···

__
alex fenton
http://www.pressure.to/cccp/ --still anxious–

There’s been some discussion
(http://www.rubygarden.org/article.php?sid=179) about changing IO to
make this task (and other tasks) easier. At the moment, reopen() can
only be using with real IO objects (and won’t work with a StringIO
object).

The following will work, but the solution is not ideal. I’d like to
make it buffered (for better performance), and I’m not sure what should
happen if stop() is called when there is still data to be read. And if
you want to be able to make this work during a system call, then you’ll
need to use a separate process instead of a thread.

Hope this helps,

Paul

A very basic StringIO implementation

class StringIO
attr_reader :str

def initialize
@str = ''
end

def write(str)
@str << str
end
end

A class to redirect $stdout (or other IO object) to a StringIO object

(or other object with a write() method)

class Redirector
def initialize(from, to)
tmp = from.dup
r, w = IO.pipe
from.reopen(w)
@t = Thread.new do
begin
loop do
s = r.read(1) # TODO: can I make this buffered?
to.write(s)
end
ensure
from.reopen(tmp)
end
end
end

def stop
@t.kill
end

def self.redirect(from, to)
s = self.new(from, to)
begin
yield
ensure
s.stop
end
end
end

if FILE == $0 then
Thread.abort_on_exception = true
s = StringIO.new
r = Redirector.redirect($stdout, s) do
$stdout.puts “this is a test”
$stdout.puts "of the StringIO redirection system"
end
puts "Done redirecting."
puts "Result:\n#{s.str}"
end

···

On Wed, Aug 07, 2002 at 08:22:48AM +0900, alex f wrote:

In particular, I’m interested in doing things similar to what I did in Perl
with select and tie-ing STD filehandles to classes temporarily then
returning to program default values. I’ve seen an interesting example of a
string-based class implementing IO-like behaviour in ‘The Ruby Way’
(223-225), but I’m not sure how to manipulate Ruby’s STDOUT and $stdout to
do useful things with these sort of classes (using .reopen()?), so I’d
appreciate pointers to threads or example code.