Forum: Ruby What's going on here? (Newbie question)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
MB (Guest)
on 2006-06-07 05:35
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 S. (Guest)
on 2006-06-07 05:44
(Received via mailing list)
On 6-Jun-06, at 9:36 PM, MB wrote:

>
> 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 S. <removed_email_address@domain.invalid>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.
Matt Brown (Guest)
on 2006-06-07 05:47
(Received via mailing list)
Exactly what I was looking for, thank you.
Logan C. (Guest)
on 2006-06-07 09:45
(Received via mailing list)
On Jun 6, 2006, at 9:42 PM, Mike S. wrote:

>> 456
> rewind a file to the beginning, so:
> irb(main):004:0>  f.each {|line| puts line}
>
> Mike S. <removed_email_address@domain.invalid>
> http://www.stok.ca/~mike/
>
> 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.
Dave B. (Guest)
on 2006-06-07 10:22
(Received via mailing list)
Logan C. 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
Bryan W. (Guest)
on 2006-06-07 17:13
(Received via mailing list)
On Jun 6, 2006, at 11:43 PM, Logan C. wrote:

>>>
>>
>> => #<File:numbers.txt>
>> 456
>>
>>
>
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.
This topic is locked and can not be replied to.