c++實現tail file n,輸出file的後n行,如果行數不足則輸出整個文件
實現思路:使用緩衝區從後往前讀(避免一個個字符讀取消耗cpu),然後對換行符計數,直到遇到文件首或者行數達到要求。
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFERSIZE 1024
int get_br_pos(char *buf, int count, int &br_num);
int main(int ac, char *arv[]){
int line_num = 10;
if(ac != 2 && ac != 3){
printf("arguments error!");
exit(1);
}
if(ac == 3)
line_num = atoi(arv[2]);
++line_num;
int fd = open(arv[1], O_RDONLY);
printf("file: %s\n\n", arv[1]);
char buf[BUFFERSIZE + 1];
if(fd == -1){
perror("open file");
exit(1);
}
//lseek返回值是當前位置到文件首的偏移量,這個返回的實際上就是文件存儲內容大小
int file_size = lseek(fd, 0, SEEK_END);
int read_count;
int pos;
while(true){
//文件指針不能超出文件範圍,所以需要一下判斷
if(file_size >= BUFFERSIZE){
lseek(fd, -BUFFERSIZE, SEEK_CUR);
read_count = BUFFERSIZE;
}
else{
lseek(fd, 0, SEEK_SET);
read_count = file_size;
}
file_size -= BUFFERSIZE;
if(read(fd, buf, read_count) != read_count){
perror("read");
exit(1);
}
pos = get_br_pos(buf, read_count, line_num);
if(pos != -1 || file_size <= 0){
lseek(fd, pos + 1 - read_count, SEEK_CUR);
break;
}
lseek(fd, -BUFFERSIZE, SEEK_CUR);
}
while(true){
read_count = read(fd, buf, BUFFERSIZE);
buf[read_count] = '\0';
printf("%s",buf);
if(read_count != BUFFERSIZE)
break;
}
if(close(fd) == -1){
perror("close");
exit(1);
}
}
int get_br_pos(char *buf, int count, int &br_num){
while(--count >= 0){
if(buf[count] == '\n' && --br_num == 0){
break;
}
}
return count;
}