如何在Ruby中从底部到顶部读取文件? [英] How to read a file from bottom to top in Ruby?

查看:92
本文介绍了如何在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆