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.