Я работал над средством просмотра журнала для приложения для направляющих и нашел, что должен считать приблизительно 200 строк файла журнала от нижней части до вершины вместо значения по умолчанию, от начала до конца.
Файлы журнала могут стать довольно большими, таким образом, я уже попробовал и исключил IO.readlines ("log_file.log") [-200..-1] метод.
Там какие-либо другие пути состоят в том, чтобы пойти о чтении файла назад в Ruby без потребности в плагине или драгоценном камне?
Единственный правильный способ сделать это, который также работает с огромными файлами, - читать 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
Конечно, другие реализации уже существуют. Я не пробовал ни одну из них, поэтому не могу сказать, какая лучше.