0

I'm running irb as a one-off text preprocessing tool. I ran into immediate trouble just printing the text.

foo = File.open "bar"
foo.each_line {|l| puts l}

This prints as intended and returns #<File:emails plaintext>.

However, if I call #each_line again on the same object, no printing occurs, though it still returns #<File:emails plaintext>.

Why are the contents of the File object being overwritten by a call to #each_line? I thought the raison d'etre of #each-like methods was to ensure mutation does not occur. What is the proper 'ruby way' to do this?

  • `each` methods have nothing to do with the mutation. These concepts are orthogonal. – Sergio Tulentsev Apr 12 '13 at 20:08
  • However, I have only entered 3 lines into irb, and this has occurred, hence my confusion. My reasoning was that unless you specifically command a mutation to occur within the scope of a block passed to each, no changes will occur, nor should `#puts`-like methods alter state. –  Apr 12 '13 at 20:09
  • File is an I/O object. It has a concept of current position. You read the file to the end. There's no more content to return. – Sergio Tulentsev Apr 12 '13 at 20:11
  • Oh okay I didn't know enough about file streams –  Apr 12 '13 at 20:12
  • If you open a file this way, don't forget to close it ( `foo.close` ). – steenslag Apr 12 '13 at 21:23

1 Answers1

3

You have to rewind it: foo.rewind.

Consider how $stdin.each_line ought to behave. Since an IO object could be a file on disk, or it could be a stream or a pipe, it doesn’t make sense to guarantee that you can randomly seek around in it. Load it into an array if you want to iterate multiple times.

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
  • I appreciate the additional presentation of different options for accomplishing what I need as well as the technical explanation –  Apr 12 '13 at 20:14