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: