blackghost
blackghost

Reputation: 703

How to close and delete a file in Ruby?

Say that I open a file in Ruby like this:

f = File.open('diagram.txt', 'r')

Right now, in order to close and delete that file I have this code:

begin
  f = File.open('diagram.txt', 'r')
ensure
  if !f.nil? && File.exist?(f)
    f.close unless f.closed? 
    File.delete(f)
  end
end

I found this code to be too complicated, and the File.exist?(f) would fail if the f is closed already. So, what is the correct approach to avoid the closing and deleting of the file raising exceptions?

Note: I know that passing a block to File.open will close the file directly, however, I am looking for the general approach of closing and deleting.

Upvotes: 18

Views: 27899

Answers (3)

konsolebox
konsolebox

Reputation: 75478

Just delete the file after closing without referring to the object.

begin
  f = File.open('diagram.txt', 'r')
  # Do something with file.
ensure
  f.close unless f.nil? || f.closed?
  File.delete('diagram.txt') if File.exist? 'diagram.txt'
end

Upvotes: 15

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84343

Handling the Errno::ENOENT Exception

Since your diagram.txt file is not guaranteed to exist in your example code, your bigger problem is handling the Errno::ENOENT exception. You can Call File#open in a self-closing block, and then use rescue to handle the exception if you try to open or delete a missing file. For example:

begin
  File.open('diagram.txt', 'r') do |f|
    # do something with file
    File.delete(f)
  end
rescue Errno::ENOENT
end

Upvotes: 19

Ajedi32
Ajedi32

Reputation: 48348

Depending on your specific situation, it might be possible to use Tempfile.create. From the docs:

If a block is given, then a File object will be constructed, and the block is invoked with the object as the argument. The File object will be automatically closed and the temporally file is removed after the block terminates. The call returns the value of the block.

(Emphasis mine)

Usage:

require 'tempfile'

Tempfile.create('diagram.txt') do |f|
  # Do something with the file
end

Upvotes: 3

Related Questions