Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are all the common ways to read a file in Ruby?

Tags:

file-io

ruby

People also ask

What are the Ruby file open modes?

Ruby allows the following open modes: "r" Read-only, starts at beginning of file (default mode). "r+" Read-write, starts at beginning of file. "w" Write-only, truncates existing file to zero length or creates a new file for writing.

Which method is used writing to the file in Ruby?

Writing to the file With the help of syswrite method, you can write content into a file. File needs to be opened in write mode for this method. The new content will over write the old content in an already existing file.


The easiest way if the file isn't too long is:

puts File.read(file_name)

Indeed, IO.read or File.read automatically close the file, so there is no need to use File.open with a block.


File.open("my/file/path", "r") do |f|
  f.each_line do |line|
    puts line
  end
end
# File is closed automatically at end of block

It is also possible to explicitly close file after as above (pass a block to open closes it for you):

f = File.open("my/file/path", "r")
f.each_line do |line|
  puts line
end
f.close

Be wary of "slurping" files. That's when you read the entire file into memory at once.

The problem is that it doesn't scale well. You could be developing code with a reasonably sized file, then put it into production and suddenly find you're trying to read files measuring in gigabytes, and your host is freezing up as it tries to read and allocate memory.

Line-by-line I/O is very fast, and almost always as effective as slurping. It's surprisingly fast actually.

I like to use:

IO.foreach("testfile") {|x| print "GOT ", x }

or

File.foreach('testfile') {|x| print "GOT", x }

File inherits from IO, and foreach is in IO, so you can use either.

I have some benchmarks showing the impact of trying to read big files via read vs. line-by-line I/O at "Why is "slurping" a file not a good practice?".


You can read the file all at once:

content = File.readlines 'file.txt'
content.each_with_index{|line, i| puts "#{i+1}: #{line}"}

When the file is large, or may be large, it is usually better to process it line-by-line:

File.foreach( 'file.txt' ) do |line|
  puts line
end

Sometimes you want access to the file handle though or control the reads yourself:

File.open( 'file.txt' ) do |f|
  loop do
    break if not line = f.gets
    puts "#{f.lineno}: #{line}"
  end
end

In case of binary files, you may specify a nil-separator and a block size, like so:

File.open('file.bin', 'rb') do |f|
  loop do
    break if not buf = f.gets(nil, 80)
    puts buf.unpack('H*')
  end
end

Finally you can do it without a block, for example when processing multiple files simultaneously. In that case the file must be explicitly closed (improved as per comment of @antinome):

begin
  f = File.open 'file.txt'
  while line = f.gets
    puts line
  end
ensure
  f.close
end

References: File API and the IO API.


One simple method is to use readlines:

my_array = IO.readlines('filename.txt')

Each line in the input file will be an entry in the array. The method handles opening and closing the file for you.