Reputation: 195
In a stripped down exercise (20) from Learn Ruby the Hard Way, the script opens a file (test.txt) and prints three successive lines.
input_file = ARGV.first
def print_a_line(line_count, f)
puts "#{line_count}, #{f.gets}"
end
current_file = open(input_file)
current_line = 1
print_a_line(current_line, current_file)
current_line += 1
print_a_line(current_line, current_file)
current_line += 1
print_a_line(current_line, current_file)
The result being
$ ruby ex20.rb test.txt
1, This is line 1
2, This is line 2
3, This is line 3
I understand that gets
only "gets" one line at a time, but I can't figure out what in this script makes the "playhead" move from one line to the next in test.txt. When I remove .gets
, it looks like it stays in the same position:
$ ruby ex20.rb test.txt
1, #<File:0x00000001b9b738>
2, #<File:0x00000001b9b738>
3, #<File:0x00000001b9b738>
And when I increase the line number on current_line by += 3
, while the printed line number changes to reflect this, the content of that line doesn't:
$ ruby ex20.rb test.txt
1, This is line 1
2, This is line 2
5, This is line 3
The content of test.txt is:
This is line 1
This is line 2
This is line 3
This is line 4
This is line 5
So, how is this moving from line to line automatically, and by extension, how could I make it move to another line rather than the next successive one?
Upvotes: 1
Views: 98
Reputation: 230296
In addition to @spickermann's answer
and by extension, how could I make it move to another line rather than the next successive one?
Generally, you can't. If you want to skip, say, two lines, you can't just jump over directly to the third one. You have to read these two and ignore them.
In a specific case where all your lines have the same fixed length, you can seek
directly to a line you want (and then again, some IO streams will only allow seeking forward, not forward and backward).
I can't figure out what in this script makes the "playhead" move from one line to the next in test.txt
I sometimes visualize a typewriter, but it does the opposite thing. When you call gets
, the reading head would read current line to the end, scroll the sheet one line, rewind to the beginning of the line and pause, waiting for the next gets
.
Not sure if this was at all helpful to you, but it helps me. :)
Upvotes: 0
Reputation: 106802
From the documentation of IO#gets
:
Reads the next “line” from the I/O stream; lines are separated by sep. [...] The line read in will be returned and also assigned to $_. [...]
That said: f
is your file object. When you call gets
on that file, it will return the next line - a string up to the next new line character ("\n") and it will store the current position (line number). When you call gets
again, it can look up the last position and therefore is able to return the next line.
In the context of your example it is worth noting that line_count
and current_line
are totally independent. You can change current_line
to any value it will not change the bahaviour of f.gets
.
Upvotes: 1