La única forma correcta de hacerlo que también funciona en archivos enormes es leer n bytes a la vez desde el final hasta que tenga el número de líneas que desea. Esto es esencialmente cómo funciona Unix tail
.
Un ejemplo de implementación de IO#tail(n)
, que devuelve los últimos n
líneas como un 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
La aplicación es un poco ingenuo, pero una referencia rápida demuestra la diferencia ridícula esta sencilla aplicación ya se puede hacer (probado con un archivo de 25 MB ~ generado con 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)
El código de referencia:
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
Por supuesto, other implementations ya existen. No he probado ninguno, así que no puedo decirte cuál es el mejor.
Duplicado de: [? La lectura de las últimas n líneas de un archivo en Ruby] (http://stackoverflow.com/questions/754494) – hippietrail