Ruby's File.open and the need for f.close

RubyFile

Ruby Problem Overview


It's common knowledge in most programming languages that the flow for working with files is open-use-close. Yet I saw many times in ruby codes unmatched File.open calls, and moreover I found this gem of knowledge in the ruby docs:

> I/O streams are automatically closed when they are claimed by the garbage collector.

darkredandyellow friendly irc take on the issue:
[17:12] yes, and also, the number of file descriptors is usually limited by the OS
[17:29] I assume you can easily run out of available file descriptors before the garbage collector cleans up. in this case, you might want to use close them yourself. "claimed by the garbage collector." means that the GC acts at some point in the future. and it's expensive. a lot of reasons for explicitly closing files.

  1. Do we need to explicitly close
  2. If yes then why does the GC autoclose ?
  3. If not then why the option?

Ruby Solutions


Solution 1 - Ruby

> I saw many times in ruby codes unmatched File.open calls

Can you give an example? I only ever see that in code written by newbies who lack the "common knowledge in most programming languages that the flow for working with files is open-use-close".

Experienced Rubyists either explicitly close their files, or, more idiomatically, use the block form of File.open, which automatically closes the file for you. Its implementation basically looks something like like this:

def File.open(*args, &block)
  return open_with_block(*args, &block) if block_given?
  open_without_block(*args)
end

def File.open_without_block(*args)
  # do whatever ...
end

def File.open_with_block(*args)
  yield f = open_without_block(*args)
ensure
  f.close
end

Scripts are a special case. Scripts generally run so short, and use so few file descriptors that it simply doesn't make sense to close them, since the operating system will close them anyway when the script exits.

>Do we need to explicitly close?

Yes.

>If yes then why does the GC autoclose?

Because after it has collected the object, there is no way for you to close the file anymore, and thus you would leak file descriptors.

Note that it's not the garbage collector that closes the files. The garbage collector simply executes any finalizers for an object before it collects it. It just so happens that the File class defines a finalizer which closes the file.

>If not then why the option?

Because wasted memory is cheap, but wasted file descriptors aren't. Therefore, it doesn't make sense to tie the lifetime of a file descriptor to the lifetime of some chunk of memory.

You simply cannot predict when the garbage collector will run. You cannot even predict if it will run at all: if you never run out of memory, the garbage collector will never run, therefore the finalizer will never run, therefore the file will never be closed.

Solution 2 - Ruby

You should always close file descriptors after use, that will also flush it. Often people use http://www.ruby-doc.org/core/classes/File.html#M000069">File.open</a> or equivalent method with blocks to handle file descriptor lifetime. For example:

File.open('foo', 'w') do |f|
    f.write "bar"
end

In that example the file is closed automatically.

Solution 3 - Ruby

According to http://ruby-doc.org/core-2.1.4/File.html#method-c-open

> With no associated block, File.open is a synonym for ::new. If the > optional code block is given, it will be passed the opened file as an argument > and the File object will automatically be closed when the block > terminates. The value of the block will be returned from File.open.

Therefore, will automatically be closed when the block terminates :D

Solution 4 - Ruby

  1. Yes
  2. In case you don't, or if there is some other failure
  3. See 2.

Solution 5 - Ruby

We can use the File.read() function to read the file in ruby..... such as,

file_variable = File.read("filename.txt")

in this example file_variable can have the full value of that file....

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionclyfeView Question on Stackoverflow
Solution 1 - RubyJörg W MittagView Answer on Stackoverflow
Solution 2 - RubyTonttuView Answer on Stackoverflow
Solution 3 - RubyskozzView Answer on Stackoverflow
Solution 4 - RubySatyaView Answer on Stackoverflow
Solution 5 - RubyKumar KSView Answer on Stackoverflow