I made something like tail that displays the last n lines of a file in Ruby
I will try to imitate.
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
First, from the comment section of the original article. If you do it in Ruby, this is fine. This feature is
Such. It's surprisingly fast when I try it.
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)
Next, I wrote a tail by Ruby. A method of dividing a file into chunks of a certain size and counting the number of line breaks from the back of the trailing chunk.
Not too early.
Next is the implementation that if you are told to write tail, it will be in this 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);
}
A method of counting from the back using mmap.
There are many merits. It's really fast. Faster than the original tail.