Radek
Radek

Reputation: 11091

After reading a file ruby leaves it open/locked on Windows XP

I read a text file to get some info from it and later on I need to rename the directory that the file sits in. I am not able do to that because the file is locked. If I comment out the function that reads from the file or if I manually unlock the file (unlocker utility) everything goes fine.

I am on ruby 1.8.7 (2010-08-16 patchlevel 302) [i386-mingw32]

This line leaves the file open File.open(file).readlines.each{|line|

These two lines leave the file open

    my_file=File.open(file,"r")
    my_file.collect {|line|

unless I close the file at the end using my_file.close

The man for core 1.8.7 of IO.html#method-c-open states

If the optional code block is given, it will be passed io as an argument, and the IO object will automatically be closed when the block terminates.

So I don't understand why the file is still open.

What would be the one line code in 1.8.7 to read a text file and close it automatically?

Upvotes: 0

Views: 423

Answers (3)

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84343

If you want the block to close the file automagically without passing the file handle to a block, you can use the IO#readlines method of your File object.

array_of_lines = File.readlines('/tmp/foo')

This will read the entire contents of the file, then close the file handle. It's a good option whenever a file is small enough to fit easily into memory.

Upvotes: 1

maerics
maerics

Reputation: 156424

Try passing the block directly to the "open" call:

File.open(file, 'r') do |f|
  f.each_line do |line|
    # Process each line
  end
end

Or if you just want the file contents in a single shot then try this:

lines = File.read(file).split(/\r?\n/)

Upvotes: 1

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230306

The documentation is clear. However, you're passing the block to collect. And since you're not passing it to open, you are responsible for closing the file.

To have file auto-closed, try this:

File.open(file,"r") do |f|
  f.collect # or whatever
end

Upvotes: 5

Related Questions