如何在Ruby中从底部到顶部读取文件? [英] How to read a file from bottom to top in Ruby?
问题描述
我一直在研究Rails应用程序的日志查看器,发现我需要从底部到顶部读取大约200行日志文件,而不是默认的从顶部到底部。
日志文件可能会变得很大,所以我已经试过并排除了IO.readlines(log_file.log)[ - 200 ..- 1]方法。 b
$ b
是否有任何其他方法可以在不需要插件或gem的情况下向后读取文件?
唯一正确的方法是在读取大量文件的同时读取 n 字节,直到获得所需的行数。这基本上是Unix tail
的工作方式。
$ b
IO#tail n)
,它将最后一个 n
行返回为 Array
:
class IO
TAIL_BUF_LENGTH = 1<< 16
def tail(n)
return [] if n < 1
seek -TAIL_BUF_LENGTH,SEEK_END
buf =
而buf.count(\\\
)<= n
buf = read(TAIL_BUF_LENGTH)+ buf
seek 2 * -TAIL_BUF_LENGTH,SEEK_CUR
end
buf.split(\\\
)[ - n ..- 1]
end
end
这个实现有点幼稚,这个简单的实现已经可以做一个荒谬的区别了(用 yes> yes.txt
生成一个〜25MB的文件):
用户系统总实数
f.readlines [-200 ..- 1] 7.150000 1.150000 8.300000(8.297671)
f.tail(200)0.000000 0.000000 0.000000(0.000367)
基准代码:
要求benchmark
FILE =yes.txt
Benchmark.bmbm do | b |
b.reportf.readlines [-200 ..- 1]do
File.open(FILE)do | f |
f.readlines [-200 ..- 1]
end
end
b.reportf.tail(200)do
File .open(FILE)do | f |
f.tail(200)
结束
结束
结束
当然,其他的实现已经存在。我还没有尝试过,所以我不能告诉你哪个是最好的。
I've been working on a log viewer for a Rails app and have found that I need to read around 200 lines of a log file from bottom to top instead of the default top to bottom.
Log files can get quite large, so I've already tried and ruled out the IO.readlines("log_file.log")[-200..-1] method.
Are there any other ways to go about reading a file backwards in Ruby without the need for a plugin or gem?
The only correct way to do this that also works on enormous files is to read n bytes at a time from the end until you have the number of lines that you want. This is essentially how Unix tail
works.
An example implementation of IO#tail(n)
, which returns the last n
lines as an Array
:
class IO
TAIL_BUF_LENGTH = 1 << 16
def tail(n)
return [] if n < 1
seek -TAIL_BUF_LENGTH, SEEK_END
buf = ""
while buf.count("\n") <= n
buf = read(TAIL_BUF_LENGTH) + buf
seek 2 * -TAIL_BUF_LENGTH, SEEK_CUR
end
buf.split("\n")[-n..-1]
end
end
The implementation is a little naive, but a quick benchmark shows what a ridiculous difference this simple implementation can already make (tested with a ~25MB file generated with yes > yes.txt
):
user system total real
f.readlines[-200..-1] 7.150000 1.150000 8.300000 ( 8.297671)
f.tail(200) 0.000000 0.000000 0.000000 ( 0.000367)
The benchmark code:
require "benchmark"
FILE = "yes.txt"
Benchmark.bmbm do |b|
b.report "f.readlines[-200..-1]" do
File.open(FILE) do |f|
f.readlines[-200..-1]
end
end
b.report "f.tail(200)" do
File.open(FILE) do |f|
f.tail(200)
end
end
end
Of course, other implementations already exist. I haven't tried any, so I cannot tell you which is best.
这篇关于如何在Ruby中从底部到顶部读取文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!