在Ruby中读取文件的常用方法是什么?

dsg*_*dsg 271 ruby file-io

在Ruby中读取文件的常用方法是什么?

例如,这是一种方法:

fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
  puts(line)
end
fileObj.close
Run Code Online (Sandbox Code Playgroud)

我知道Ruby非常灵活.每种方法的好处/缺点是什么?

mck*_*eed 318

如果文件不太长,最简单的方法是:

puts File.read(file_name)
Run Code Online (Sandbox Code Playgroud)

确实,IO.read或者File.read自动关闭文件,因此不需要使用File.open块.

  • `IO.read`或`File.read`也会自动关闭文件,尽管你的措辞让它听起来不像. (15认同)
  • 他已经说过"如果文件不太长".完美适合我的情况. (15认同)

fl0*_*00r 250

File.open("my/file/path", "r") do |f|
  f.each_line do |line|
    puts line
  end
end
# File is closed automatically at end of block
Run Code Online (Sandbox Code Playgroud)

也可以像上面那样显式关闭文件(传递一个块来open为你关闭它):

f = File.open("my/file/path", "r")
f.each_line do |line|
  puts line
end
f.close
Run Code Online (Sandbox Code Playgroud)

  • 这不是惯用的Ruby.使用`foreach`而不是`open`并省去`each_line`块. (13认同)
  • `f.each {| line | ...}`和`f.each_line {| line | ...}`似乎有相同的行为(至少在Ruby 2.0.0中). (6认同)

the*_*Man 222

警惕"啜饮"文件.那是你一次将整个文件读入内存的时候.

问题是它不能很好地扩展.您可以使用合理大小的文件开发代码,然后将其投入生产并突然发现您正在尝试读取以千兆字节为单位的文件,并且主机在尝试读取和分配内存时会冻结.

逐行I/O非常快,几乎总是像啜饮一样有效.实际上它的速度非常快.

我喜欢用:

IO.foreach("testfile") {|x| print "GOT ", x }
Run Code Online (Sandbox Code Playgroud)

要么

File.foreach('testfile') {|x| print "GOT", x }
Run Code Online (Sandbox Code Playgroud)

文件继承自IO,并且foreach在IO中,因此您可以使用其中任何一个.

我有一些基准测试显示尝试通过read逐行I/O 读取大文件的影响" 为什么"啜饮"文件不是一个好的做法? ".

  • 这正是我想要的。我有一个500万行的文件,真的不希望将其加载到内存中。 (6认同)
  • 它来自编程历史。这是一个起点https://www.perl.com/article/21/2013/4/21/Read-an-entire-file-into-a-string/ (2认同)

Vic*_*los 68

您可以一次读取所有文件:

content = File.readlines 'file.txt'
content.each_with_index{|line, i| puts "#{i+1}: #{line}"}
Run Code Online (Sandbox Code Playgroud)

当文件很大或可能很大时,通常最好逐行处理:

File.foreach( 'file.txt' ) do |line|
  puts line
end
Run Code Online (Sandbox Code Playgroud)

有时您希望访问文件句柄或自己控制读取:

File.open( 'file.txt' ) do |f|
  loop do
    break if not line = f.gets
    puts "#{f.lineno}: #{line}"
  end
end
Run Code Online (Sandbox Code Playgroud)

如果是二进制文件,您可以指定nil-separator和块大小,如下所示:

File.open('file.bin', 'rb') do |f|
  loop do
    break if not buf = f.gets(nil, 80)
    puts buf.unpack('H*')
  end
end
Run Code Online (Sandbox Code Playgroud)

最后,您可以在没有块的情况下执行此操作,例如同时处理多个文件时.在这种情况下,必须显式关闭文件(根据@antinome的注释进行改进):

begin
  f = File.open 'file.txt'
  while line = f.gets
    puts line
  end
ensure
  f.close
end
Run Code Online (Sandbox Code Playgroud)

参考:文件APIIO API.

  • 文件或IO中没有`for_each`.请改用[`foreach`](http://www.ruby-doc.org/core-2.1.2/IO.html#method-c-foreach). (2认同)

bta*_*bta 26

一种简单的方法是使用readlines:

my_array = IO.readlines('filename.txt')
Run Code Online (Sandbox Code Playgroud)

输入文件中的每一行都是数组中的一个条目.该方法为您处理打开和关闭文件.

  • 与`read`或任何变体一样,这会将整个文件拉入内存,如果文件大于可用内存,则会导致严重问题.另外,因为它是一个数组,Ruby必须创建数组,另外减慢进程. (5认同)

Kum*_* KS 20

file_content = File.read('filename with extension');
puts file_content;
Run Code Online (Sandbox Code Playgroud)

http://www.ruby-doc.org/core-1.9.3/IO.html#method-c-read


saw*_*awa 9

我经常这样做:

open(path_in_string, &:read)
Run Code Online (Sandbox Code Playgroud)

这将为您提供整个文本作为字符串对象.它只适用于Ruby 1.9.

  • 它关闭它,但它不可扩展所以要小心. (5认同)