- Know how to use
getsto read input. - Know why
chompis often used to clean input. - Know the difference between
printandputs. - Know how to open a file
- Know how to read a line from a file.
- Know how to read in all the lines from a file.
- Know how to slurp in a whole file in one go.
- Know when you have to close a file explicitly.
- Know how to access arguments given to your script from the command line
The most basic IO methods are Kernel#gets and
Kernel#puts:
input = gets
puts input # put it back outgets will read a line from the standard input, which is usually
the terminal the user is typing into. It returns the string the user
typed, including the newline character (newline character is the
'return' character, written "\n")
input = gets # I type Hello world!, and press enter
# input == "Hello world!\n"Because the newline is often undesired, frequently we use
String#chomp to remove it
input = gets.chomp
# get a string from the input, chop off the newline, store it in
# inputprint converts its argument to a string by calling Object#to_s,
then it writes it out to the standard output.
print "this that other" # prints 'this that other' to console
print [1, 2, 3] # prints '[1, 2, 3]' to consoleprint doesn't add a newline after it prints output, which means
consecutive calls to print all print to the same line.
print "this"
print "that" # => prints "thisthat"
print "\n" # => adds a newline
print "I'm on a new line"Since it's common to want to add newlines to the end, Ruby has another
method puts. It's pretty simple:
puts "this" # => prints "this" with a newlineFinally, there is the Kernel#p method, which is like puts, but is
used for debugging and the REPL (REPL means read-eval-print loop;
irb is the standard Ruby REPL). Instead of calling Object#to_s, p
calls Object#inspect. The main difference is:
puts "this" # => prints "this" with a newline
p "this" # => prints '"this"' with a newline; note the quotesNotice also that puts adds newlines after each object in an array.
puts [1, 2, 3]
# prints:
# 1
# 2
# 3If you want to print an array out on one line, you probably want p.
You often want to read data in from files, rather than the console. The typical way to open a file is as follows:
File.open("movie-times.txt") do |f|
first_line = f.gets.chomp
# ...
endThe class method File::open opens a file. You pass a block, and the
block will be called with a File object passed in. To read data from
a file, you can call File#gets, which works like Kernel#gets,
except it reads from the file, rather than console.
If, as is often the case, you want to do something once for each line:
File.foreach("movie-times.txt") do |line|
# ...
endFinally, if you'd like to read the entire file into one long string, you may write:
contents = File.read("movie-times.txt")To read the lines individually, use readlines:
contents = File.readlines("movie-times.txt")
# returns an array, with each element representing a line of
# "movie-times.txt"
# Note: Each element will end with '\n'The File class includes Enumerable adding all the power we know
and love from arrays. Here's an example of using #each.
f = File.new("todos")
f.each {|line| puts "#{f.lineno}: #{line}" }To open a file for writing, you need to pass "w" to File.open for
write mode:
File.open("cool-things.txt", "w") do |f|
f.puts "Race cars"
f.puts "Lasers"
f.puts "Aeroplanes"
endNote: "w" mode will create a new file or overwrite an existing
file. If you wish append to an existing file, you will need to use
"a". For more file mode options check
this SO post.
The examples I've shown you have all automatically closed the file when done. It is important to close files when you are finished with them; this doesn't matter so much for reading (it is merely inefficient), but if you don't close a file you are writing to, then the whole output may not be written to disk, and you may lose data.
If you use File::open without a block, it returns an open File
object. You'll be responsible for calling #close when you're done.
f = File.open("cool-things.txt", "w")
f.puts "Race cars"
f.puts "Lasers"
f.puts "Aeroplanes"
# will make sure output is "synced" to disk and properly saved
f.closeBecause it is error-prone to rely on remembering to #close a file,
prefer the block version of ::open, ::foreach, or ::read
whenever possible. These will all automatically #close the file.
We've seen the methods Kernel#puts and Kernel#gets as well as
File#puts and File#gets. Surprise! They're related!
In *nix operating systems (like Linux, BSD, and OS X), the console input and output are just special files. You can read and write to them like any other file. These are called standard input and standard output.
In Ruby, you can access standard input and output through the global
variables $stdout and $stdin. These variables just hold typical
File objects. In particular, Kernel#gets and Kernel#puts just
call $stdin.gets and $stdout.puts.
Remembering that $stdin is a File object and that File objects
include Enumerable you'll realize that you can #each over input.
$stdin.each do |input|
puts "I was given: #{ input }"
endA user can pass arguments to your script from the command line. For example, if your script counts a list of cats, the user could pass the name of a file that contains a list of cats:
$ ruby my_cat_counter.rb list_of_cats.txt
To access the filename passed in, use ARGV in your script.
ARGV returns an array of strings that were typed after
your script name. Example:
puts ARGV
# returns ["list_of_cats.txt"]
puts ARGV[0]
# prints "list_of_cats.txt"- Beginning Ruby (Ch. 9, p. 203 in the 2nd Edition)
- Ruby IO Class