让我们先将数据写入文件。
FName = "temp"
File.write FName, "Extension Date\nstate\nCO\nCOLORADO\n\n"
检查一下。
puts File.read FName
# Extension Date
# state
# CO
# COLORADO
#
现在执行您的代码,添加一些 puts 语句。
file = File.open(FName)
loop do
enum = file.each_line
puts "enum = #{enum}"
puts "enum's object id = #{ enum.object_id }"
puts "file.pos = #{file.pos}"
puts "enum.peek = #{enum.peek}"
puts "enum.peek = #{enum.peek}"
end
file.close
打印以下内容。前五行是:
enum = #<Enumerator:0x007feb528d8bd8>
file.pos = 0
enum's object id = 70324339525100
enum.peek = Extension Date
enum.peek = Extension Date
文件位置(如上所示)最初是0。我们查看文件中的下一行,即"Extention Date\n"。 Ruby 必须提前文件指针来读取第一行代码。然而,在她这样做之后,她并没有将文件位置重置为零,如下所示 (file.pos #=> 0 + "Extention Date\n".size => 15)。我们还看到第二个 enum.peek 的文件指针没有再次前进,这表明 Ruby 将该值保存在缓冲区中。
enum = #<Enumerator:0x007feb528d8868>
enum's object id = 70324339524660
file.pos = 15
enum.peek = state
创建了一个新的枚举器,从enum 的返回值和更改后的object_id 都可以看出。此枚举器从文件偏移量15 开始。 peek 返回 state\n 将文件指针前进到 15 + "state\n".size #=> 21`(见下文)。
enum = #<Enumerator:0x007feb528d84f8>
enum's object id = 70324339524220
file.pos = 21
enum.peek = CO
创建第三个枚举器,从文件偏移量21 开始。 peek 返回CO\n,将文件指针前进到21 + "CO\n".size #=> 24。
enum = #<Enumerator:0x007feb528d8188>
enum's object id = 70324339523780
file.pos = 24
enum.peek = COLORADO
创建了第四个枚举器,从文件偏移量24 开始。 peek 返回COLORADO\n,将文件指针前进到24 + "COLORADO\n".size #=> 33。
enum = #<Enumerator:0x007feb528d3db8>
enum's object id = 70324339515100
file.pos = 33
enum.peek =
从文件偏移量33 开始创建第五个枚举器。 peek 返回\n,将文件指针前进到33 + "\n".size #=> 34。
# enum = #<Enumerator:0x007feb528d3a48>
# enum's object id = 70324339514660
# file.pos = 34
创建了第六个枚举器,从文件偏移量34 开始。 peek 引发 StopIteration 异常,由 Kernel#loop 通过跳出循环来处理。
显然,您不想继续创建新的枚举器。只需执行以下操作。
file = File.open(FName)
enum = file.each_line
loop do
line = enum.next
puts line
end
file.close
# Extension Date
# state
# CO
# COLORADO
我使用了Enumerator#next 而不是Enumerator#peek,因为对于文件,它们具有相同的效果,而next 可以更好地传达正在执行的操作。
请注意,File.close 通常会被省略,因为当文件句柄超出范围时,Ruby 会关闭文件。
我建议你改用 IO::foreach:
File.foreach(FName) do |line|
puts line
end
# Extension Date
# state
# CO
# COLORADO
#
foreach 也逐行读取文件,但在退出块时将其关闭。请注意,因为File 是IO (File < IO #=> true) 的子类,所以IO 类方法通常以File 作为接收者编写。