在Ruby中读取文件的所有常用方法是什么?
例如,这是一种方法:
fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
puts(line)
end
fileObj.close
我知道Ruby非常灵活。每种方法的好处/缺点是什么?
答案 0 :(得分:292)
如果文件不太长,最简单的方法是:
puts File.read(file_name)
确实,IO.read
或File.read
会自动关闭文件,因此无需将File.open
与块一起使用。
答案 1 :(得分:246)
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
也可以如上所述显式关闭文件(将块传递给open
为你关闭):
f = File.open("my/file/path", "r")
f.each_line do |line|
puts line
end
f.close
答案 2 :(得分:211)
警惕“啜饮”文件。那是你一次将整个文件读入内存的时候。
问题是它不能很好地扩展。您可以使用合理大小的文件开发代码,然后将其投入生产并突然发现您正在尝试读取以千兆字节为单位的文件,并且主机在尝试读取和分配内存时会冻结。
逐行I / O非常快,几乎总是像啜饮一样有效。实际上它的速度非常快。
我喜欢使用:
IO.foreach("testfile") {|x| print "GOT ", x }
或
File.foreach('testfile') {|x| print "GOT", x }
文件继承自IO,foreach
位于IO中,因此您可以使用。
我有一些基准测试显示尝试通过read
与“Why is "slurping" a file not a good practice?”的逐行I / O读取大文件的影响。
答案 3 :(得分:67)
您可以一次阅读所有文件:
content = File.readlines 'file.txt'
content.each_with_index{|line, i| puts "#{i+1}: #{line}"}
当文件很大或可能很大时,通常最好逐行处理:
File.foreach( 'file.txt' ) do |line|
puts line
end
有时您希望访问文件句柄或自己控制读取:
File.open( 'file.txt' ) do |f|
loop do
break if not line = f.gets
puts "#{f.lineno}: #{line}"
end
end
如果是二进制文件,您可以指定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
最后,您可以在没有块的情况下执行此操作,例如同时处理多个文件时。在这种情况下,必须明确关闭文件(根据@antinome的评论进行改进):
begin
f = File.open 'file.txt'
while line = f.gets
puts line
end
ensure
f.close
end
答案 4 :(得分:25)
答案 5 :(得分:17)
file_content = File.read('filename with extension');
puts file_content;
答案 6 :(得分:9)
我通常这样做:
open(path_in_string, &:read)
这将为整个文本提供一个字符串对象。它仅适用于Ruby 1.9。
答案 7 :(得分:4)
从your_file.log或.txt
返回最后 n 行path = File.join(Rails.root, 'your_folder','your_file.log')
last_100_lines = `tail -n 100 #{path}`
答案 8 :(得分:0)
一种更有效的方法是通过请求操作系统的内核打开文件,然后一点一点地从文件中读取字节来进行流传输。在Ruby中每行读取一个文件时,一次从512字节的文件中提取数据,然后将其分成几行。
通过缓冲文件的内容,减少了I / O调用的数量,同时将文件划分为逻辑块。
示例:
将此类作为服务对象添加到您的应用中:
class MyIO
def initialize(filename)
fd = IO.sysopen(filename)
@io = IO.new(fd)
@buffer = ""
end
def each(&block)
@buffer << @io.sysread(512) until @buffer.include?($/)
line, @buffer = @buffer.split($/, 2)
block.call(line)
each(&block)
rescue EOFError
@io.close
end
end
调用它,并将:each
方法传递给一个块:
filename = './somewhere/large-file-4gb.txt'
MyIO.new(filename).each{|x| puts x }
在此详细的帖子中阅读有关内容:
答案 9 :(得分:0)
如果文件较小(拖拉):
puts File.read("filename.txt")
如果文件很大(流):
File.foreach("filename.txt") { |line| puts line }
答案 10 :(得分:-1)
content = `cat file`
我认为这种方法是最“罕见”的方法。也许有点棘手,但是如果安装了cat
,它就可以工作。