Easy Tutorial
❮ Ruby Iterators Ruby Loop ❯

Ruby File Input and Output

Ruby provides a complete set of I/O-related methods implemented in the Kernel module. All I/O methods are derived from the IO class.

The IO class provides all the basic methods, such as read, write, gets, puts, readline, getc, and printf.

This section will explain all the basic I/O functions available in Ruby. For more functions, see the Ruby IO class.

puts Statement

In previous chapters, you assigned values to variables and printed them using the puts statement.

The puts statement instructs the program to display the value stored in the variable. This adds a new line at the end of each line.

Example

#!/usr/bin/ruby

val1 = "This is variable one"
val2 = "This is variable two"
puts val1
puts val2

The output of the above example is:

This is variable one
This is variable two

gets Statement

The gets statement can be used to take input from the standard screen called STDIN.

Example

The following code demonstrates how to use the gets statement. This code will prompt the user to enter a value, which will be stored in the variable val and finally printed on STDOUT.

Example

#!/usr/bin/ruby

puts "Enter a value :"
val = gets
puts val

The output of the above example is:

Enter a value :
This is entered value
This is entered value

putc Statement

Unlike the puts statement, which outputs the entire string to the screen, the putc statement can be used to output one character at a time.

Example

The output of the following code is just the character H:

Example

#!/usr/bin/ruby

str = "Hello Ruby!"
putc str

The output of the above example is:

H

print Statement

The print statement is similar to the puts statement. The only difference is that the puts statement goes to a new line after printing the contents, whereas with the print statement, the cursor is positioned on the same line.

Example

#!/usr/bin/ruby

print "Hello World"
print "Good Morning"

The output of the above example is:

Hello WorldGood Morning

Opening and Closing Files

So far, you have read and written to standard input and output. Now, we will see how to manipulate actual data files.

File.new Method

You can create a File object using File.new for reading, writing, or both, depending on the mode string. Finally, you can use File.close to close the file.

Syntax

aFile = File.new("filename", "mode")
   # ... process the file
aFile.close

File.open Method

You can use File.open to create a new file object and assign it to a file. However, there is a difference between File.open and File.new. The difference is that the File.open method can be associated with a block, whereas the File.new method cannot.

File.open("filename", "mode") do |aFile|
   # ... process the file
end

The following table lists the different modes to open a file:

Mode Description
r Read-only mode. The file pointer is placed at the beginning of the file. This is the default mode.
r+ Read-write mode. The file pointer is placed at the beginning of the file.
w Write-only mode. Overwrites the file if the file exists. If the file does not exist, creates a new file for writing.
w+ Read-write mode. Overwrites the existing file if the file exists. If the file does not exist, creates a new file for reading and writing.
a Write-only mode. The file pointer is at the end of the file if the file exists. That is, the file is in the append mode. If the file does not exist, it creates a new file for writing.
a+ Read-write mode. The file pointer is at the end of the file if the file exists. That is, the file is in the append mode. If the file does not exist, it creates a new file for reading and writing.

Reading and Writing Files

The methods used for simple I/O are also available for all file objects. So, gets reads a line from standard input, and aFile.gets reads a line from the file object aFile.

However, the I/O objects provide additional settings for accessing methods that provide convenience.

sysread Method

You can use the sysread method to read the contents of a file. When using the sysread method, you can open a file in any mode. For example:

Here is an input text file:

This is a simple text file for testing purposes.

Now let's try to read this file:

Example

#!/usr/bin/ruby

aFile = File.new("input.txt", "r")
if aFile
   content = aFile.sysread(20)
   puts content
else
   puts "Unable to open file!"
end

This statement will read the first 20 characters of the input file. The file pointer will be placed at the 21st character position.

syswrite Method

You can use the syswrite method to write content to a file. When using the syswrite method, you need to open the file in write mode. For example:

Example

#!/usr/bin/ruby

aFile = File.new("input.txt", "r+")
if aFile
   aFile.syswrite("ABCDEF")
else
   puts "Unable to open file!"
end

This statement will write "ABCDEF" to the file.

each_byte Method

This method belongs to the File class. The each_byte method is useful for iterating over each character in a string. See the following code example:

Example

#!/usr/bin/ruby

aFile = File.new("input.txt", "r+")
if aFile
   aFile.syswrite("ABCDEF")
   aFile.rewind
   aFile.each_byte {|ch| putc ch; putc ?. }
else
   puts "Unable to open file!"
end

Characters are passed one by one to the variable ch and then displayed on the screen as follows:

A.B.C.D.E.F.s. .a. .s.i.m.p.l.e. .t.e.x.t. .f.i.l.e. .f.o.r. .t.e.s.t.i.n.g. .p.u.r.p.o.s.e...

IO.readlines Method

The File class is a subclass of the IO class. The IO class also has some methods for manipulating files.

IO.readlines is a method in the IO class. This method returns the contents of the file line by line. The following code shows the use of the IO.readlines method:

Example

#!/usr/bin/ruby

arr = IO.readlines("input.txt")
puts arr[0]
puts arr[1]

In this code, the variable arr is an array. Each line of the file input.txt will be an element in the array arr. Therefore, arr[0] will contain the first line, and arr[1] will contain the second line of the file.

IO.foreach Method

This method also returns output line by line. The difference between the foreach method and the readlines method is that the foreach method is associated with a block. However, unlike the readlines method, the foreach method does not return an array. For example:

Example

#!/usr/bin/ruby

IO.foreach("input.txt"){|block| puts block}

This code will pass each line of the file test to the variable block, and then the output will be displayed on the screen.

Renaming and Deleting Files

You can rename and delete files using the rename and delete methods.

The following example renames an existing file test1.txt:

Example

#!/usr/bin/ruby

# Rename file test1.txt to test2.txt
File.rename( "test1.txt", "test2.txt" )

The following example deletes an existing file test2.txt:

Example

#!/usr/bin/ruby

# Delete file test2.txt
File.delete("test2.txt")

File Modes and Ownership

Use the chmod method with a mask to change the mode or permissions/access list of a file:

The following example changes the mode of an existing file test.txt to a mask value:

Example

#!/usr/bin/ruby

file = File.new( "test.txt", "w" )
file.chmod( 0755 )

The following table lists the different masks used with the chmod method:

Mask Description
0700 rwx mask for owner
0400 r for owner
0200 w for owner
0100 x for owner
0070 rwx mask for group
0040 r for group
0020 w for group
0010 x for group
0007 rwx mask for others
0004 r for others
0002 w for others
0001 x for others
4000 Set user ID on execution
2000 Set group ID on execution
1000 Save swapped text, even after use

File Inquiry

The following command checks if a file exists before opening it:

Example

#!/usr/bin/ruby

File.open("file.rb") if File::exists?( "file.rb" )

The following command checks if the given file name is indeed a file:

Example

#!/usr/bin/ruby

# Returns true or false
File.file?( "text.txt" )

The following command checks whether the given file name is a directory:

Example

#!/usr/bin/ruby

# A directory
File::directory?( "/usr/local/bin" ) # => true

# A file
File::directory?( "file.rb" ) # => false

The following commands check if the file is readable, writable, and executable:

Example

#!/usr/bin/ruby

File.readable?( "test.txt" )   # => true
File.writable?( "test.txt" )   # => true
File.executable?( "test.txt" ) # => false

The following command checks if the file size is zero:

Example

#!/usr/bin/ruby

File.zero?( "test.txt" )      # => true

The following command returns the size of the file:

Example

#!/usr/bin/ruby

File.size?( "text.txt" )     # => 1002

The following command is used to check the type of file:

Example

#!/usr/bin/ruby

File::ftype( "test.txt" )     # => file

The ftype method identifies the type of a file by returning one of the following values: file, directory, characterSpecial, blockSpecial, fifo, link, socket, or unknown.

The following command is used to check the creation, modification, or last access time of a file:

Example

#!/usr/bin/ruby

File::ctime("test.txt") # => Fri May 09 10:06:37 -0700 2008
File::mtime("text.txt") # => Fri May 09 10:44:44 -0700 2008
File::atime("text.txt") # => Fri May 09 10:45:01 -0700 2008

Directories in Ruby

All files are contained within directories, and Ruby provides methods to handle files and directories. The File class is used for handling files, and the Dir class is used for handling directories.

Browsing Directories

To change the directory in a Ruby program, use Dir.chdir. The following example changes the current directory to /usr/bin.

Dir.chdir("/usr/bin")

You can view the current directory with Dir.pwd:

puts Dir.pwd # Returns the current directory, like /usr/bin

You can get a list of files and directories within a specified directory using Dir.entries:

puts Dir.entries("/usr/bin").join(' ')

Dir.entries returns an array containing all entries in the specified directory. Dir.foreach provides the same functionality:

Dir.foreach("/usr/bin") do |entry|
   puts entry
end

A more concise way to get a directory list is by using Dir's array-like methods:

Dir["/usr/bin/*"]

Creating Directories

Dir.mkdir can be used to create directories:

Dir.mkdir("mynewdir")

You can also set permissions on a new directory (not an existing one) with mkdir:

Note: The mask 755 sets permissions for the owner, group, and world to rwxr-xr-x, where r = read, w = write, x = execute.

Dir.mkdir("mynewdir", 755)

Deleting Directories

Dir.delete can be used to delete directories. Dir.unlink and Dir.rmdir perform the same function, providing convenience.

Dir.delete("testdir")

Creating Files & Temporary Directories

Temporary files are those created briefly during program execution but are not stored permanently.

Dir.tmpdir provides the path to the temporary directory on the current system, but this method is not available by default. To make Dir.tmpdir available, requiring 'tmpdir' is necessary.

You can use Dir.tmpdir with File.join to create a platform-independent temporary file:

require 'tmpdir'
tempfilename = File.join(Dir.tmpdir, "tingtong")
tempfile = File.new(tempfilename, "w")
tempfile.puts "This is a temporary file"
tempfile.close
File.delete(tempfilename)

This code creates a temporary file, writes data to it, and then deletes the file. Ruby's standard library also includes a Tempfile library for creating temporary files:

require 'tempfile'
f = Tempfile.new('tingtong')
f.puts "Hello"
puts f.path
f.close

Built-in Functions

Below is a complete list of built-in functions in Ruby for handling files and directories:

❮ Ruby Iterators Ruby Loop ❯