What's going on here? (Newbie question)

In irb:

f = File.new('numbers.txt')
=> #<File:numbers.txt>

f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>

f.each {|line| puts line}
=> #<File:numbers.txt>

Why doesn't the second f.each work?

···

--
Posted via http://www.ruby-forum.com/.

because as each iterates through the file it "consumes" the file contents (well, it remembers how far it has got.) You can usually rewind a file to the beginning, so:

irb(main):001:0> f = File.new('numbers.txt')
=> #<File:numbers.txt>
irb(main):002:0> f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>
irb(main):003:0> f.pos
=> 12
irb(main):004:0> f.each {|line| puts line}
=> #<File:numbers.txt>
irb(main):005:0> f.pos
=> 12
irb(main):006:0> f.rewind
=> 0
irb(main):007:0> f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>

Note that some types of file can't be rewound.

Take a look at what the pos method does, and see if this makes sense.

Hope this helps,

Mike

···

On 6-Jun-06, at 9:36 PM, MB wrote:

In irb:

f = File.new('numbers.txt')
=> #<File:numbers.txt>

f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>

f.each {|line| puts line}
=> #<File:numbers.txt>

Why doesn't the second f.each work?

--

Mike Stok <mike@stok.ca>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.

Exactly what I was looking for, thank you.

···

On 6/6/06, Mike Stok <mike@stok.ca> wrote:

On 6-Jun-06, at 9:36 PM, MB wrote:

> In irb:
>
> f = File.new('numbers.txt')
> => #<File:numbers.txt>
>
> f.each {|line| puts line}
> 123
> 456
> 789
> => #<File:numbers.txt>
>
> f.each {|line| puts line}
> => #<File:numbers.txt>
>
> Why doesn't the second f.each work?

because as each iterates through the file it "consumes" the file
contents (well, it remembers how far it has got.) You can usually
rewind a file to the beginning, so:

irb(main):001:0> f = File.new('numbers.txt')
=> #<File:numbers.txt>
irb(main):002:0> f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>
irb(main):003:0> f.pos
=> 12
irb(main):004:0> f.each {|line| puts line}
=> #<File:numbers.txt>
irb(main):005:0> f.pos
=> 12
irb(main):006:0> f.rewind
=> 0
irb(main):007:0> f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>

Note that some types of file can't be rewound.

Take a look at what the pos method does, and see if this makes sense.

Hope this helps,

Mike

--

Mike Stok <mike@stok.ca>
Mike Stok

The "`Stok' disclaimers" apply.

I wonder if IO#each should be changed to automatically #rewind at the beginning of #each (if possible). I have difficulty imagining a situation where someone would purposely do
a = file.gets
file.each { ... }

But I can certainly imagine people iterating over a file multiple times. OTOH this may be too magical.

···

On Jun 6, 2006, at 9:42 PM, Mike Stok wrote:

On 6-Jun-06, at 9:36 PM, MB wrote:

In irb:

f = File.new('numbers.txt')
=> #<File:numbers.txt>

f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>

f.each {|line| puts line}
=> #<File:numbers.txt>

Why doesn't the second f.each work?

because as each iterates through the file it "consumes" the file contents (well, it remembers how far it has got.) You can usually rewind a file to the beginning, so:

irb(main):001:0> f = File.new('numbers.txt')
=> #<File:numbers.txt>
irb(main):002:0> f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>
irb(main):003:0> f.pos
=> 12
irb(main):004:0> f.each {|line| puts line}
=> #<File:numbers.txt>
irb(main):005:0> f.pos
=> 12
irb(main):006:0> f.rewind
=> 0
irb(main):007:0> f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>

Note that some types of file can't be rewound.

Take a look at what the pos method does, and see if this makes sense.

Hope this helps,

Mike

--

Mike Stok <mike@stok.ca>
Mike Stok

The "`Stok' disclaimers" apply.

Logan Capaldo wrote:

I wonder if IO#each should be changed to automatically #rewind at the
beginning of #each (if possible). I have difficulty imagining a
situation where someone would purposely do
a = file.gets
file.each { ... }

But I can certainly imagine people iterating over a file multiple
times. OTOH this may be too magical.

Too magical. Streams are often one-way. If you need to read the same
data from the same stream more than once, usually the appropriate
method is to store the data in a variable to avoid that. Instead of:

  f.each {|s| foo }
  f.reset
  f.each {|s| bar }

This may often work better:

  data = f.read
  data.each {|s| foo }
  data.each {|s| bar }

Cheers,
Dave

What about using:

f = IO.readlines(file)

Then the entire file contents will be loaded line-by-line as an array. You wouldn't have to worry about rewinding the position in the actual file.

···

On Jun 6, 2006, at 11:43 PM, Logan Capaldo wrote:

On Jun 6, 2006, at 9:42 PM, Mike Stok wrote:

On 6-Jun-06, at 9:36 PM, MB wrote:

In irb:

f = File.new('numbers.txt')
=> #<File:numbers.txt>

f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>

f.each {|line| puts line}
=> #<File:numbers.txt>

Why doesn't the second f.each work?

because as each iterates through the file it "consumes" the file contents (well, it remembers how far it has got.) You can usually rewind a file to the beginning, so:

irb(main):001:0> f = File.new('numbers.txt')
=> #<File:numbers.txt>
irb(main):002:0> f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>
irb(main):003:0> f.pos
=> 12
irb(main):004:0> f.each {|line| puts line}
=> #<File:numbers.txt>
irb(main):005:0> f.pos
=> 12
irb(main):006:0> f.rewind
=> 0
irb(main):007:0> f.each {|line| puts line}
123
456
789
=> #<File:numbers.txt>

Note that some types of file can't be rewound.

Take a look at what the pos method does, and see if this makes sense.

Hope this helps,

Mike

--

Mike Stok <mike@stok.ca>
Mike Stok

The "`Stok' disclaimers" apply.

I wonder if IO#each should be changed to automatically #rewind at the beginning of #each (if possible). I have difficulty imagining a situation where someone would purposely do
a = file.gets
file.each { ... }

But I can certainly imagine people iterating over a file multiple times. OTOH this may be too magical.