Как считать файл от нижней части до вершины в Ruby?

Я работал над средством просмотра журнала для приложения для направляющих и нашел, что должен считать приблизительно 200 строк файла журнала от нижней части до вершины вместо значения по умолчанию, от начала до конца.

Файлы журнала могут стать довольно большими, таким образом, я уже попробовал и исключил IO.readlines ("log_file.log") [-200..-1] метод.

Там какие-либо другие пути состоят в том, чтобы пойти о чтении файла назад в Ruby без потребности в плагине или драгоценном камне?

13
задан ericalli 11 June 2010 в 16:11
поделиться

1 ответ

Единственный правильный способ сделать это, который также работает с огромными файлами, - читать n байт за раз с конца, пока не будет получено нужное вам количество строк. По сути, так работает tail в Unix.

Пример реализации IO#tail(n), которая возвращает последние n строк в виде массива:

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

Реализация немного наивна, но быстрый бенчмарк показывает, какую смешную разницу может сделать эта простая реализация (проверено на файле размером ~25 МБ, сгенерированном с помощью 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)

Код бенчмарка:

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

Конечно, другие реализации уже существуют. Я не пробовал ни одну из них, поэтому не могу сказать, какая лучше.

17
ответ дан 1 December 2019 в 22:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: