1. 程式人生 > >linux檔案管理小結之自定義more

linux檔案管理小結之自定義more

1.more命令功能

more命令用於檢視內容超過一屏的文字(類似於cat)
基本功能
1.輸入backspace :內容翻一屏
2.輸入enter : 內容翻一行
3.輸入q:退出
4.實時顯示已讀檔案比例

2.實現思路

  1. 從命令中獲取需要操作的檔案
  2. 開啟檔案:open(filename,O_RDONLY);
  3. 獲取檔案總行數:
    lseek(fd,0,SEEK_END);//移動檔案指標至檔案末
    page_sum = lseek(fd,0,SEEK_CUR);//計算與檔案頭偏移量,即可得到檔案總行數
  4. 命令初始讀取內容(定義整屏為10行)
    設定一標誌量 儲存 每次需要顯示的行數,假設n,則執行n次下操作
    用read(fd,str,1); 每次讀取一個位元組,讀到’\n’停止
    並且在每次讀完之後需要用lseek(fd,0,SEEK_CUR)來獲取當前已顯示行數,用於得到檔案已閱比例
  5. 每次操作完成後接受使用者指令
    see_more();
    函式接受使用者輸入,根據輸入值返回要翻的頁數
  6. close(fd);

過程收穫

  1. 反顯文字:
    做這個時才瞭解到linux 上 printf的功能好豐富,清屏,移動游標,一應俱全;
  2. 保證more的提示資訊總顯示在終端的最下端,並不重複顯示
    剛開始準備使用,printf(“\033[s”)記錄游標位置,輸出後,再用printf(“\033[u\033[K”);游標歸位並清行;
    然而在輸出提示資訊中,還需要接受使用者的輸入,會產生換行符,而換行之後,游標歸位會失效,記錄於此。
    最終是用printf(“\033[1A\033[K”)將游標上移一行,並清空該行內容,用以覆蓋提示資訊
  3. 檔案比例的實現
    這個的實現細節上文已經提到,之所以再做贅述,是因為筆者在實現過程中因為此功能卡頓很久
    因為需要按行讀的緣故,想要使用fgets()來讀取文字,但是開啟檔案又用的是系統函式open(),而非fopen(),於是就產生了混用的情況。
    而結果是每次用lseek()讀取當前檔案指標偏移量時,得到的值都是檔案首與檔案尾的偏移量,改為fseek()後,值變為0,探究無果,不知其因,記錄於此,日後再談

程式碼

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #define PAGENUM 10 //定義一屏為10行 void do_more(int fd); int see_more( int sum, int now); int main( int argc, char **argv ) { int fd; if( argc == 1 )//引數不合法則返回 { return 0; } else { while( argc-->1 ) { if( (fd = open(*++argv,O_RDONLY)) != -1 ) { do_more(fd); close(fd); } else { printf("Error: can't open file\n"); exit(1); } } } return 0; } void do_more(int fd) { char str[3]; int page_num = 0;//儲存每次需要跳轉的行數 int rel; int page_now = 0;//儲存當前行數(初始為0) int page_sum;//儲存總行數 lseek(fd,0,SEEK_END);//移動檔案指標至檔案末 page_sum = lseek(fd,0,SEEK_CUR);//計算與檔案頭偏移量,即檔案總行數 lseek(fd,0,SEEK_SET);//移動檔案指標至檔案頭 while( page_now<page_sum ) { while(read(fd,str,1))//每次讀一行 { if(str[0] =='\n') { printf("\n"); break; } printf("%c",str[0]); } page_now = lseek(fd, 0, SEEK_CUR);//實時更新已讀行數 if( page_num == PAGENUM ) { rel = see_more( page_sum, page_now);//獲取使用者輸入 printf("\033[1A\033[K");//將游標上移一行,並清空該行內容,用以覆蓋提示資訊 if( rel == 0 ) { break; } else { page_num -= rel; } } page_num++; } } int see_more(int sum,int now) { int rel; printf("\033[7m --更多-- enter翻行 backspace翻頁 q退出 %.2f%% \033[0m",now*100.0/sum);//反顯輸出提示資訊以及檔案已讀比例 while(rel = getchar()) { if(rel == 'q') { return 0; } if(rel == ' ') { return PAGENUM; } if(rel == '\n') { return 1; } } return 0; }