Data processing is a common task in programming. Data can come from many places: files, network, database, etc. In this post you will learn how to work with files and folders in Ruby.
The file class allows you to open a file by simply passing in the file name to the open method:
1 |
file = File.open("users.txt") |
Since File
is a sub-class of the IO class, you can work with file objects using IO
methods. For example, using gets you can read one line at a time, and using read you can read the whole file or a specified number of bytes.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Read the first line file.gets # => "user1\n" # Go back to the start of the file file.rewind # Read the whole file file.read # => "user1\nuser2\nuser3\n" # We are done, close the file. file.close |
You will need to remember to call close on your file, so the contents are flushed to disk (if you wrote to it) and the file descriptor is made available.
If you want to read the whole file with just one line of code you can use File.read
, in this case you don’t need to close the file. There is also a File.write counterpart to this method.
1 2 |
data = File.read("users.txt") # => "user1\nuser2\nuser3\n" |
If you want to process the file one line at a time, you can use the foreach method:
1 |
File.foreach("users.txt") { |line| puts line } |
File writing is pretty easy too. When opening a file for writing, we need to add the “w” flag as the second argument.
1 |
File.open("log.txt", "w") { |f| f.write "#{Time.now} - User logged in\n" } |
This will rewrite the previous file contents. If you want add to the file, use the “a” (append) flag.
Another way to write data into a file is to use File.write
:
1 |
File.write("log.txt", "data...") |
Other than reading and writing there are other operations you may want to do on files. For example, you may want to know if a file exist or get a list of files for the current directory. Let’s see a few examples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# Renaming a file File.rename("old-name.txt", "new-name.txt") # File size in bytes File.size("users.txt") # Does this file already exist? File.exists?("log.txt") # Get the file extension, this works even if the file doesn't exists File.extname("users.txt") # => ".txt" # Get the file name without the directory part File.basename("/tmp/ebook.pdf") # => "ebook.pdf" # Get the path for this file, without the file name File.dirname("/tmp/ebook.pdf") # => "/tmp" # Is this actually a file or a directory? File.directory?("cats") |
The last example makes more sense if we are looping through the contents of a directory listing.
1 2 3 4 |
def find_files_in_current_directory entries = Dir.entries(".") entries.reject { |entry| File.directory?(entry) } end |
Using Dir.glob you can get a list of all the files that match a certain pattern, here are some examples:
1 2 3 4 5 6 7 8 |
# All files in current directory Dir.glob("*") # All files containing "spec" in the name Dir.glob("*spec*") # All ruby files Dir.glob("*.rb") |