简体   繁体   中英

File.delete throws Errno:EACCESS Permission Denied in ruby

The following code that is meant to delete lines that match a regular expression fails

def delete_entry(name)
    puts "Deleting #{name}.." if $DEBUG
    begin
      File.open("#{@file_name}.tmp", 'w') do |out_file|
        File.open(@file_name, 'r').each do |line|
          unless line =~ /^#{name},/
            out_file.print line
          else
            puts "Deleted #{line}!"
          end
        end
      end
      File.delete(@file_name)
      File.rename("#{@file_name}.tmp", @file_name)
    rescue Exception
      puts "Exception thrown in PhoneBook::delete_entry(#{name}): #{$!}"
    end
  end

The temporary file works just fine. The corresponding entries are deleted properly. But when I try to delete the old file, and rename the tmp to the new file, File.delete throws the following: (line 56 is the call to File#delete)

Exception `Errno::EACCES' at PhoneBook.rb:56 - Permission denied - file-io-sampl
es/phonebooks/test.csv
Exception thrown in PhoneBook::delete_entry(Mike): Permission denied - file-io-s
amples/phonebooks/test.csv

Any help would be appreciated. This is on Windows 7 using a NTFS filesystem if that helps matters.

Edit: As per Az's suggestion in the comments I added:

ObjectSpace.each_object(File) { |f| p f if f.path == @file_name && !f.closed? }

Just before the call to File.delete. The output is below:

C:\Pickaxe>ruby PhoneBook.rb true
Enter a phonebook!
test.csv
Using test.csv..
Open Called!
Name: Richard Sex: Male Age: 22
Name: Midori Sex: Female Age: 22
Name: Mike Sex: Male Age:  18
Name: Richard Sex: Male Age: 44
Deleting Mike..
Deleted Mike,Male, 18
!
#<File:file-io-samples/phonebooks/test.csv>
#<File:file-io-samples/phonebooks/test.csv>
Exception `Errno::EACCES' at PhoneBook.rb:56 - Permission denied - file-io-sampl
es/phonebooks/test.csv
Exception thrown in PhoneBook::delete_entry(Mike): Permission denied - file-io-s
amples/phonebooks/test.csv

C:\Pickaxe>

The two lines prefixed with # is the output of the ObjectSpace call.

I figured this out as I stated my last comment on the original post. The problem was is I wasn't calling open with a block and therefore did not benefit from the automatic f.close that comes with using File.open with a block.

To remedy this I used File.open do |file| file.each, instead of File.open(..).each

def delete_entry(name)
    puts "Deleting #{name}.." if $DEBUG
    begin
      File.open("#{@file_name}.tmp", 'w') do |out_file|
        File.open(@file_name, 'r+') do |file|
          file.each do |line|
            unless line =~ /^#{name},/
              out_file.print line
            else
              puts "Deleted #{line}!"
            end
          end
        end
      end
      ObjectSpace.each_object(File) { |f| p f if f.path == @file_name && !f.closed? } if $DEBUG
      File.delete(@file_name)
      File.rename("#{@file_name}.tmp", @file_name)
    rescue Exception
      puts "Exception thrown in PhoneBook::delete_entry(#{name}): #{$!}"
    end
  end

As a general tip to anyone who finds this while trying to diagnose the error themselves, try deleting the file manually via the command line first. That may show you that you have permissions issues on the file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM