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


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net