Существуют важные различия между этими тремя вариантами.
File.open("file").each_line { |line| puts line }
File.open
открывает локальный файл и возвращает файл-объект IO#close
на нем open("file").each_line { |line| puts line }
Kernel.open
смотрит на строку, чтобы решить, что с ней делать.
open(".irbrc").class # => File
open("http://google.com/").class # => StringIO
File.open("http://google.com/") # => Errno::ENOENT: No such file or directory - http://google.com/
Во втором случае объект StringIO
, возвращенный Kernel#open
, фактически содержит содержимое http://google.com/ . Если Kernel#open
возвращает объект File
, он остается открытым, пока вы не назовете IO#close
на нем.
IO.foreach("file") { |line| puts line }
IO.foreach
открывает файл, называет данный блок для каждой прочитанной строки и закрывает файл впоследствии. File.read("file").each { |line| puts line }
Вы не упомянули об этом выборе, но это тот, который я использовал бы в большинстве случаев.
File.read
полностью читает файл и возвращает его как строку. IO.foreach
это дает понять, что вы имеете дело с файлом. В этой ситуации это не удается:
s= File.read("/dev/zero") # => never terminates
s.each …
ri - это инструмент, который показывает вам рубиновую документацию. Вы используете его так же на своей оболочке.
ri File.open
ri open
ri IO.foreach
ri File#each_line
С этим вы можете найти почти все, что я написал здесь, и многое другое.