Redirecting Standard Input or Output






Redirecting Standard Input or Output

Problem

You don't want the standard input, output, or error of your process to go to the default IO objects set up by the Ruby interpreter. You want them to go to other filetype objects of your own choosing.

Solution

You can assign any IO object (a File, a Socket, or what have you) to the global variables $stdin, $stdout, or $stderr. You can then read from or write to those objects as though they were the originals.

This short Ruby program demonstrates how to redirect the Kernel methods that print to standard output. To avoid confusion, I'm presenting it as a standalone Ruby program rather than an interactive irb session.[4]

[4] irb prints the result of each Ruby expression to $stdout, which tends to clutter the results in this case.

	#!/usr/bin/ruby -w
	# ./redirect_stdout.rb
	require 'stringio'
	new_stdout = StringIO.new

	$stdout = new_stdout
	puts "Hello, hello."
	puts "I'm writing to standard  
output."

	$stderr.puts "#{new_stdout.size} bytes written to standard ouput so far."
	$stderr.puts "You haven't seen anything on the screen yet, but you soon will:"
	$stderr.puts new_stdout.string

Run this program and you'll see the following:

	$ ruby redirect_stdout.rb
	46 bytes written to standard output so far.
	You haven't seen anything on the screen yet, but you soon will:
	Hello, hello.
	I'm writing to standard output.

Discussion

If you have any Unix experience, you know that when you run a Ruby script from the command line, you can make the shell redirect its standard input, output, and error streams to files or other programs. This technique lets you do the same thing from within a Ruby script.

You can use this as a quick and dirty way to write errors to a file, write output to a StringIO object (as seen above), or even read input from a socket. Within a script, you can programatically decide where to send your output, or receive standard input from multiple sources. These things are generally not possible from the command line without a lot of fancy shell scripting.

The redirection technique is especially useful when you've written or inherited a script that prints text to standard output, and you need to make it capable of printing to any file-like object. Rather than changing almost every line of your code, you can just set $stdout at the start of your program, and let it run as is. This isn't a perfect solution, but it's often good enough.

The original input and output streams for a process are always available as the constants STDIN, STDOUT, and STDERR. If you want to temporarily swap one IO stream for another, change back to the "standard" standard output by setting $stdin = STDIN. Keep in mind that since the $std objects are global variables, even a temporary change affects all threads in your script.

See Also

Recipe 6.15, "Pretending a String Is a File," has much more information on StringIO



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows