tail -n c++實現

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章