3

私がやろうとしているのは、ファイル名をメソッドに渡し、ファイルが閉じているかどうかを確認することです。私が苦労しているのは、実際にファイルを開かずにファイル名からファイル オブジェクトを取得することです。

def file_is_closed(file_name)
  file = # The method I am looking for
  file.closed?
end

コメントの部分を埋める必要があります。YAML モジュールの load_file メソッドを使用してみましたが、実際のファイルではなくファイルの内容が表示されると思います。

File モジュールで呼び出すメソッドが見つかりませんでした。多分私が知らない方法はありますか?

4

2 に答える 2

1

File#closed?その特定の File オブジェクトが閉じているかどうかを返すため、現在試行されているソリューションを機能させるメソッドはありません。

f1 = File.new("test.file")
f2 = File.new("test.file")
f1.close
f1.closed? # => true # Even though f2 still has the same file open

可能であれば、使用している File オブジェクトを保持して、閉じているかどうかを確認することをお勧めします。

現在の Ruby プロセスが特定のパスに対して開いている File オブジェクトを持っているかどうかを本当に知りたい場合は、次のようなものがハックのように感じますが、ほとんどの場合うまくいくはずです。

def file_is_closed?(file_name)
  ObjectSpace.each_object(File) do |f|
    if File.absolute_path(f) == File.absolute_path(file_name) && !f.closed?
      return false
    end
  end

  true
end

私はコーナーケースをうまく処理することを支持していませんが、一般的にはうまくいくようです:

f1 = File.new("test.file")
f2 = File.new("test.file")
file_is_closed?("test.file") # => false
f1.close
file_is_closed?("test.file") # => false
f2.close
file_is_closed?("test.file") # => true

プロセスがファイルを開いているかどうかを知りたい場合は、のような外部のものに頼る必要があると思いますlsof

于 2013-06-07T03:49:07.593 に答える
0

Ruby で元のファイル オブジェクトにアクセスできなくなった場合 (たとえば、fork + exec の後) は、開いているファイル記述子のリストが /proc/pid/fd にあります。そこにある各ファイルは、ファイル記述子番号の名前が付けられており、開いているファイル、パイプ、またはソケットへのシンボリック リンクです。

# Returns hash in form fd => filename
def open_file_descriptors
  Hash[
  Dir.glob( File.join( '/proc', Process.pid.to_s, 'fd', '*' ) ).
    map { |fn| [File.basename(fn).to_i, File.readlink(fn)] rescue [nil, nil] }.
    delete_if { |fd, fn| fd.nil? or fd < 3 }
  ]
end

# Return IO object for the named file, or nil if it's not open
def io_for_path(path)
  fd, fn = open_file_descriptors.find {|k,v| path === v}
  fd.nil? ? nil : IO.for_fd(fd)
end

# close an open file
file = io_for_path('/my/open/file')
file.close unless file.nil?

メソッドは fd ディレクトリを解析し、open_file_descriptors{3 => '/my/open/file'} のようなハッシュを返します。次に、目的のファイルのファイル記述子番号を取得し、Ruby に IO オブジェクトを生成させるのは簡単なことですfor_fd

もちろん、これは Linux を使用していることを前提としています。

于 2013-06-07T13:04:09.530 に答える