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