[RUBY] Schwanz implementieren

Ich habe so etwas wie einen Schwanz gemacht, der die letzten n Zeilen einer Datei in Ruby anzeigt

Versuche nachzuahmen.

Einfache Version

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

Zunächst aus dem Kommentarbereich des Originalartikels. Wenn Sie es mit Ruby machen, fühlt sich das gut an. Diese Funktion ist

Eine solche. Es ist überraschend schnell, wenn ich es versuche.

Pufferversion

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)

Als nächstes schrieb ich einen Schwanz von Ruby. Eine Methode zum Teilen einer Datei in Blöcke einer bestimmten Größe und zum Zählen der Anzahl der Zeilenumbrüche von der Rückseite des nachfolgenden Blocks.

Nicht zu früh.

mmap version

Als nächstes folgt die Implementierung, dass, wenn Sie aufgefordert werden, Tail zu schreiben, dies in diese Richtung erfolgt.

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);
}

Eine Methode zum Zählen von hinten mit mmap.

Es gibt viele Vorzüge. Es ist sehr schnell. Schneller als der ursprüngliche Schwanz.

Recommended Posts

Schwanz implementieren
Implementieren Sie die Rails-Paginierung
Lassen Sie uns Lexer (1) implementieren
Lassen Sie uns Lexer (2) implementieren
Lassen Sie uns EAM implementieren