0

正規表現に一致する行を削除するための次のコードは失敗します

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

一時ファイルは正常に機能します。該当するエントリは適切に削除されます。しかし、古いファイルを削除して、tmp の名前を新しいファイルに変更しようとすると、File.delete は次のメッセージをスローします: (56 行目は 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

どんな助けでも大歓迎です。問題が解決する場合、これは NTFS ファイルシステムを使用する Windows 7 上にあります。

編集:私が追加したコメントでのAzの提案に従って:

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

File.delete の呼び出しの直前。出力は以下のとおりです。

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>

# で始まる 2 行は、ObjectSpace 呼び出しの出力です。

4

2 に答える 2

2

元の投稿に対する最後のコメントを述べたときに、これを理解しました。問題は、ブロックで open を呼び出していなかったため、ブロックで File.open を使用することに伴う自動 f.close の恩恵を受けられなかったことです。

これを改善するために、File.open do |file| を使用しました。File.open(..).each の代わりに file.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
于 2013-05-20T05:29:41.477 に答える