In this part of the Ruby tutorial, we will talk about Input & output operations in Ruby. The input is any data that is read by the program, either from a keyboard, file or other programs. The output is data that is produced by the program. The output may go to the screen, to a file or to another program.
Input & output is a large topic. We bring forward some examples to give you a general idea of the subject. Several classes in Ruby have methods for doing input/output operations. For example
According to the Ruby documentation, the
Ruby has another three methods for printing output.
Printing data to the console using the kernel methods is a shortcut. A convenient way to print data. The following example shows a more formal way to print data to the terminal.
On Unix systems the standard terminal output is connected to a special file called /dev/tty. By opening it and writing to it, we write to a console.
The
The common way to read data from the console is to use the
In the following two scripts, we will discuss the
To get the correct answer, we need to remove the newline character. This is a job for the
We will have a similar example, which will show additional methods in action.
In the second example, we show a few methods of the
Next, we will be reading data from the files on the disk.
The next example will read data from a file.
In the second example, we retrieve all entries of a directory. Both files and directories.
The third example works with a home directory. Every user in a computer has a unique directory assigned to him. It is called a home directory. It is a place where he can place his files and create his own hierarchy of directories.
We show another two ways of running external programs in Ruby.
We can execute a command with the
In this part of the Ruby tutorial, we worked with input and output operations in Ruby.
Input & output is a large topic. We bring forward some examples to give you a general idea of the subject. Several classes in Ruby have methods for doing input/output operations. For example
Kernel
, IO
, Dir
or File
. Writing to console
Ruby has several methods for printing output on the console. These methods are part of theKernel
module. Methods of the Kernel
are available to all objects in Ruby. #!/usr/bin/rubyThe
print "Apple "
print "Apple\n"
puts "Orange"
puts "Orange"
print
and puts
methods produce textual output on the console. The difference between the two is that the latter adds a new line character. print "Apple "The print method prints two consecutive "Apple" strings to the terminal. If we want to create a new line, we must explicitly include the newline character. The newline character is '\n'. Behind the scenes. the
print "Apple\n"
print
method actually calls the to_s
method of the object being printed. puts "Orange"The
puts "Orange"
puts
method prints two strings to the console. They are on a separate line. The method includes automatically the newline character. $ ./printing.rbOutput of the printing.rb script file.
Apple Apple
Orange
Orange
According to the Ruby documentation, the
print
method is an equivalent to the $stdout.print
. The $stdout
is a global variable which holds the standard output stream. #!/usr/bin/rubyWe print two lines using the
$stdout.print "Ruby language\n"
$stdout.puts "Python language"
$stdout
variable. Ruby has another three methods for printing output.
#!/usr/bin/rubyIn the example, we present
p "Lemon"
p "Lemon"
printf "There are %d apples\n", 3
putc 'K'
putc 0xA
p
, printf
and putc
methods. p "Lemon"The
p
calls the inspect
method upon the object being printed. The method is useful for debugging. printf "There are %d apples\n", 3The
printf
method is well known from the C programming language. It enables string formatting. putc 'K'The
putc 0xA
putc
method prints one character to the console. The second line prints a newline. The 0xA is a hexadecimal code for the newline character. $ ./printing3.rbOutput of the example.
"Lemon"
"Lemon"
There are 3 apples
K
Printing data to the console using the kernel methods is a shortcut. A convenient way to print data. The following example shows a more formal way to print data to the terminal.
ios = IO.new STDOUT.filenoIn the example, we open a standard output stream and write a string into it.
ios.write "ZetCode\n"
ios.close
ios = IO.new STDOUT.filenoThe
new
method returns a stream to which we can write data. The method takes a numeric file descriptor. The STDOUT.fileno
gives us the file descriptor for the standard output stream. We could also simply write 2. ios.write "ZetCode\n"We write a string to the opened stream.
ios.closeThe input stream is closed.
On Unix systems the standard terminal output is connected to a special file called /dev/tty. By opening it and writing to it, we write to a console.
#!/usr/bin/rubyA small example in which we write to a /dev/tty file. This only works on Unix.
fd = IO.sysopen "/dev/tty", "w"
ios = IO.new(fd, "w")
ios.puts "ZetCode"
ios.close
fd = IO.sysopen "/dev/tty", "w"The
sysopen
method opens the given path, returning the underlying file descriptor number. ios = IO.new(fd, "w")The file descriptor number is used to open a stream.
ios.puts "ZetCode"We write a string to the stream and close it.
ios.close
Reading input from console
In this section, we will create some code examples that will deal with reading from the console.The
$stdin
is a global variable that holds a stream for the standard input. It can be used to read input from the console. #!/usr/bin/rubyIn the above code, we use the
inp = $stdin.read
puts inp
read
method to read input from the console. inp = $stdin.readThe
read
method reads data from the standard input, until it reaches the end of the file. The EOF is produced by pressing Ctrl + D on Unix or Ctrl + Z on Windows. $ ./reading.rbWhen we launch a program without a parameter, the script reads data from the user. It reads until we press Ctrl + D or Ctrl + Z.
Ruby language
Ruby language
$ echo "ZetCode" | ./reading.rbThe script can read data from another program or a file, if we do some redirections.
ZetCode
$ ./input.rb < stones
Garnet
Topaz
Opal
Amethyst
Ruby
Jasper
Pyrite
Malachite
Quartz
The common way to read data from the console is to use the
gets
method. #!/usr/bin/rubyWe use the
print "Enter your name: "
name = gets
puts "Hello #{name}"
gets
method to read a line from the user. name = getsThe
gets
method reads a line from the standard input. The data is assigned to the name variable. puts "Hello #{name}"The data that we have read is printed to the console. We use interpolation to include the variable in the string.
$ ./readline.rbSample output.
Enter your name: Jan
Hello Jan
In the following two scripts, we will discuss the
chomp
method. It is a string method. It removes white spaces from the end of the string, if present. It is useful when doing input operations. The method name and usage comes from the Perl language. #!/usr/bin/rubyWe read a string from a user and calculate the length of the input string.
print "Enter a string: "
inp = gets
puts "The string has #{inp.size} characters"
$ ./nochomp.rbThe message says that the string has 5 characters. It is because it counts the newline as well.
Enter a string: Ruby
The string has 5 characters
To get the correct answer, we need to remove the newline character. This is a job for the
chomp
method. #!/usr/bin/rubyThis time we use we cut the newline character with the
print "Enter a string: "
inp = gets.chomp
puts "The string has #{inp.size} characters"
chomp
method. $ ./chomp.rbThe Ruby string has indeed 4 characters.
Enter a string: Ruby
The string has 4 characters
Files
From the official Ruby documentation we learn that theIO
class is the basis for all input and output in Ruby. The File
class is the only subclass of the IO
class. The two classes are closely related. #!/usr/bin/rubyIn the first example, we open a file and write some data to it.
f = File.open('output.txt', 'w')
f.puts "The Ruby tutorial"
f.close
f = File.open('output.txt', 'w')We open a file 'output.txt' in a write mode. The
open
method returns an io stream. f.puts "The Ruby tutorial"We used the above opened stream to write some data. The
puts
method can be used to write data to a file as well. f.closeAt the end the stream is closed.
$ ./simplewrite.rbWe execute the script and show the contents of the output.txt file.
$ cat output.txt
The Ruby tutorial
We will have a similar example, which will show additional methods in action.
#!/usr/bin/rubyIf there is a block after the
File.open('langs', 'w') do |f|
f.puts "Ruby"
f.write "Java\n"
f << "Python\n"
end
open
method, then Ruby passes the opened stream to this block. At the end of the block, the file is automatically closed. f.puts "Ruby"We use three different methods to write to a file.
f.write "Java\n"
f << "Python\n"
$ ./simplewrite2.rbWe execute the script and check the contents of the langs file.
$ cat langs
Ruby
Java
Python
In the second example, we show a few methods of the
File
class. #!/usr/bin/rubyThe example creates a new file named 'tempfile' and calls some methods.
puts File.exists? 'tempfile'
f = File.new 'tempfile', 'w'
puts File.mtime 'tempfile'
puts f.size
File.rename 'tempfile', 'tempfile2'
f.close
puts File.exists? 'tempfile'The
exists?
method checks, if a file with a given name already exists. The line returns false, because we have not yet created the file. f = File.new 'tempfile', 'w'The file is created.
puts File.mtime 'tempfile'The
mtime
method gives us the last modification time of the file. puts f.sizeWe determine the file size. The method returns 0, since we have not written to the file.
File.rename 'tempfile', 'tempfile2'Finally, we rename the file using the
rename
method. $ ./testfile.rbSample output.
false
2011-11-05 16:19:36 +0100
0
Next, we will be reading data from the files on the disk.
#!/usr/bin/rubyThis is a simple script, that will open a file called stones and print it contents line by line to the terminal.
f = File.open("stones")
while line = f.gets do
puts line
end
f.close
f = File.open("stones")We open a 'stones' file. The default mode is a read mode. The 'stones' file contains nine names of valued stones; each on a separate line.
while line = f.gets doThe
puts line
end
gets
method reads a line from the I/O stream. The while block ends when we reach the end of file. $ ./readlines2.rbOutput of the example.
Garnet
Topaz
Opal
Amethyst
Ruby
Jasper
Pyrite
Malachite
Quartz
The next example will read data from a file.
#!/usr/bin/rubyThis script is another way, how we can read contents of a file. The code example will print its own code to the terminal.
fname = 'alllines.rb'
File.readlines(fname).each do |line|
puts line
end
File.readlines(fname).each do |line|The
puts line
end
readlines
reads all lines from the specified file and returns them in the form of an array. We go through the array with the each
method and print the lines to the terminal. $ ./alllines.rbOutput of the example.
#!/usr/bin/ruby
fname = 'alllines.rb'
File.readlines(fname).each do |line|
puts line
end
Directories
In this section, we work with directories. We have aDir
class to work with directories in Ruby. #!/usr/bin/rubyIn the script we use four methods of the
Dir.mkdir "tmp"
puts Dir.exists? "tmp"
puts Dir.pwd
Dir.chdir "tmp"
puts Dir.pwd
Dir.chdir '..'
puts Dir.pwd
Dir.rmdir "tmp"
puts Dir.exists? "tmp"
Dir
class. Dir.mkdir "tmp"The
mkdir
method makes a new directory called 'tmp'. puts Dir.exists? "tmp"With the
exists?
method, we check if a directory with a given name exists in the filesystem. puts Dir.pwdThe
pwd
method prints a current working directory. It is a directory, where we have launched the script. Dir.chdir '..'The
chdir
method changes to another directory. The '..' directory is the parent directory of the current working directory. Dir.rmdir "tmp"Finally, we remove a directory with the
puts Dir.exists? "tmp"
rmdir
method. This time the exists?
method returns false. $ ./dirs.rbOutput of the example.
true
/home/vronskij/programming/ruby/io
/home/vronskij/programming/ruby/io/tmp
/home/vronskij/programming/ruby/io
false
In the second example, we retrieve all entries of a directory. Both files and directories.
#!/usr/bin/rubyThe
fls = Dir.entries '.'
puts fls.inspect
entries
method returns all entries of a given diretory. fls = Dir.entries '.'We get the array of files and directories of a current directory. The '.' character stands for the current working directory in this constext. The
puts fls.inspect
inspect
method gives us a more readable representation of the array. $ ./allfiles.rbIn the output we can see an array of files and directories.
["putc.rb", "simplewrite.rb", "readlines2.rb", "fileexists.rb~" ...
The third example works with a home directory. Every user in a computer has a unique directory assigned to him. It is called a home directory. It is a place where he can place his files and create his own hierarchy of directories.
#!/usr/bin/rubyThe script prints two home directories.
puts Dir.home
puts Dir.home 'root'
puts Dir.homeIf we do not specify the user name, then a home directory of a current user is returned. The current user is the owner of the script file. Someone, who has launched the script.
puts Dir.home 'root'Here we print the home directory of a specific user. In our case the superuser.
$ ./homedir.rbSample output.
/home/vronskij
/root
Executing external programs
Ruby has several ways to execute external programs. We will deal with some of them. In our examples we will use well known Linux commands. Readers with Windows or Mac can use commands specific for their systems.#!/usr/bin/rubyWe call a
data = system 'ls'
puts data
ls
command, which lists directory contents. data = system 'ls'The
system
command executes an external program in a subshell. The method belongs to the Kernel
Ruby module. $ ./system.rbA sample output.
allfiles.rb characters.rb fileexists.rb homedir.rb~ ...
We show another two ways of running external programs in Ruby.
#!/usr/bin/rubyTo run external programs we can use backticks `` or %x[] characters.
out = `pwd`
puts out
out = %x[uptime]
puts out
out = %x[ls | grep 'readline']
puts out
out = `pwd`Here we execute the
pwd
command using backticks. The command returns the current working directory. out = %x[uptime]Here we get the output of the
uptime
command, which tells how long a system is running. out = %x[ls | grep 'readline']We can use also a combination of commands.
$ ./system2.rbSample output.
/home/vronskij/programming/ruby/io
22:50:50 up 5:32, 1 user, load average: 0.46, 0.44, 0.45
readline.rb
readline.rb~
readlines2.rb
readlines2.rb~
We can execute a command with the
open
method. The method belongs to the Kernel
module. It creates an IO object connected to the given stream, file, or subprocess. If we want to connect to a subprocess, we start the path of the open
with a pipe character (|). #!/usr/bin/rubyIn the example, we print the outcome of the
f = open("|ls -l |head -3")
out = f.read
puts out
f.close
puts $?.success?
ls -l | head -3
commands. The combination of these two commands return the first three lines of the ls -l
command. We also check the status of the child subprocess. f = open("|ls -l |head -3")We connect to a subprocess, created by these two commands.
out = f.readWe read and print data from the subprocess.
puts out
f.closeWe close the file handler.
puts $?.success?The
$?
is a special Ruby variable, which obtains the status of the last executed child process. The success?
method returns true, if the child process ended OK, false otherwise. $ ./system3.rbSample output.
total 148
-rwxr-xr-x 1 vronskij vronskij 57 2011-10-30 23:33 allfiles.rb
-rwxr-xr-x 1 vronskij vronskij 58 2011-10-30 23:33 allfiles.rb~
true
Redirecting standard output
Ruby has predefined global variables for standard input, standard output and standard error output. The$stdout
is the name of the variable for the standard output. #!/usr/bin/rubyIn the above example, we redirect a standard output to the output.log file.
$stdout = File.open "output.log", "a"
puts "Ruby"
puts "Java"
$stdout.close
$stdout = STDOUT
puts "Python"
$stdout = File.open "output.log", "a"This line creates a new standard ouput. The standard output will now flow to the ouput.log file. The file is opened in an append mode. If the file does not exist yet, it is created. Otherwise it is opened and the data is written at the end of the file.
puts "Ruby"We print two strings. The strings will not be shown in the terminal as usual, they will be appended to the output.log file.
puts "Java"
$stdout.closeWe close the handler.
$stdout = STDOUTWe use a predefined standard constant
puts "Python"
STDOUT
to recreate the normal standard ouput. The "Python" string is printed to a console. In this part of the Ruby tutorial, we worked with input and output operations in Ruby.
0 comments:
Post a Comment