J'ai créé quelque chose comme tail qui affiche les n dernières lignes d'un fichier en Ruby
J'essaierai d'imiter.
tail_simple.rb
file_path = ARGV[0]
row_limit = ARGV[1].to_i
buffer = []
File.foreach(file_path) do |line|
buffer << line
buffer.shift if buffer.size > row_limit
end
puts buffer
Tout d'abord, à partir de la section des commentaires de l'article original. Si vous le faites avec Ruby, cela fait du bien. Cette fonction est
Tel. C'est étonnamment rapide quand je l'essaye.
tail_buffered.rb
def reverse_chunks(file, size)
n = file.size / size
n -= 1 if file.size == n * size
len = file.size - n * size
until n < 0
file.seek(n * size)
yield file.read(len)
n -= 1
len = size
end
end
def offset_of_nth_chr_from_tail(file, count, target)
offset = 0
reverse_chunks(file, 1024*16) do |chunk|
chunk.size.times do |i|
chr = chunk[chunk.size - i - 1]
if chr == target || (offset == 0 && i == 0 && chr != target)
count -= 1
if count < 0
offset += i
return offset
end
end
end
offset += chunk.size
end
offset
end
def tail(fname, n_lines)
open(fname) do |file|
offset = offset_of_nth_chr_from_tail(file, n_lines, "\n")
file.seek(file.size - offset)
print file.read
end
end
tail(ARGV[0], ARGV[1].to_i)
Ensuite, j'ai écrit une queue de Ruby. Méthode de division d'un fichier en morceaux d'une certaine taille et de comptage du nombre de sauts de ligne à partir de l'arrière du morceau de fin.
Pas trop tôt.
Vient ensuite l'implémentation selon laquelle si on vous dit d'écrire tail, ce sera dans cette direction.
tail_mmap.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
void tail(char *fname, int n_lines) {
int fd = open(fname, O_RDONLY);
struct stat st;
fstat(fd, &st);
int fsize = st.st_size;
char *map = mmap(0, fsize, PROT_READ, MAP_PRIVATE, fd, 0);
char *cursor = map+fsize;
if (fsize > 0 && cursor[-1] != '\n') n_lines--;
for (int i = 0; i < fsize; i++){
cursor--;
if (*cursor == '\n') n_lines--;
if (n_lines < 0){
cursor++;
break;
}
}
write(1, cursor, fsize-(cursor-map));
munmap(map, fsize);
close(fd);
}
int main(int argc, char *argv[]){
if(argc != 3) exit(EXIT_FAILURE);
tail(argv[1], atoi(argv[2]));
exit(EXIT_SUCCESS);
}
Une méthode de comptage à partir de l'arrière en utilisant mmap.
Il y a de nombreux avantages. C'est vraiment rapide. Plus rapide que la queue d'origine.