2012-08-30 26 views
1

我有一個將結果寫入文件的程序,我希望從該文件實時讀取。這是一個普通的文本文件,外部程序總是寫一整行。我需要在Linux系統上運行它。從正在修改的文件中讀取C

int last_read = 0; 
int res; 
FILE *file; 
char *buf; 
char *end = buf + MAXLINE - 1; 
int c; 
int fileSize; 
char *dst; 
while (external_programme_is_running()) { 
    file = fopen(logfile, "r"); //without opening and closing it's not working 
    fseek(file, 0, SEEK_END); 
    fileSize = ftell(file); 
    if (fileSize > last_read) { 
     fseek(file, last_read, SEEK_SET); 
     while (!feof(file)) { 
     dst = buf; 
     while ((c = fgetc(file)) != EOF && c != '\n' && dst < end) 
      *dst++ = c; 
     *dst = '\0'; 
     res = ((c == EOF && dst == buf) ? EOF : dst - buf); 

     if (res != -1) { 
      last_read = ftell(file); 
      parse_result(buf) 
     } 
     } 
    } 
    fclose(file); 
} 

這是一個正確的方法嗎?或者,檢查修改時間然後打開文件會更好嗎?如果文件將在同一時間被修改,讀取可能會崩潰嗎?

+0

漂亮的比賽條件蛋糕... – 2012-08-30 23:05:34

+0

爲什麼不使用管道?那麼你不必經歷文件共享,開放和尋求的麻煩。看到這個:http://stackoverflow.com/questions/1072125/how-does-piping-work-in-linux –

+0

外部程序由便攜式批處理系統(PBS隊列)調度。當到達停頓時間(超時)時,PBS是否也會終止管道進程? – Tombart

回答

3

爲了避免需要關閉,重新打開並重新尋找每個循環迭代,請在讀取EOF後在流上調用clearerr

+0

謝謝,我不知道那個函數,我會試試。 – Tombart

1

如果您在閱讀其他程序的同時寫入,則不應該有任何問題。最糟糕的情況是,直到下次打開文件時纔會看到寫入內容。

此外,比較最後一個查找位置和文件末尾的方法是查找文件添加的好方法,因爲外部程序只是簡單地寫入其他行。儘管如此,我建議在循環結束時添加一個睡眠(1),所以不要使用大量的CPU。

+0

謝謝。是的,我在那裏有一個睡眠(1)函數'external_programme_is_running()'這也需要一些時間 – Tombart

0

在另一個進程寫入文件時讀取文件沒有問題。標準tail -f實用程序經常用於該目的。

唯一需要注意的是寫入過程不能專門鎖定文件。

關於您的閱讀代碼(即使用fgetc()),由於您說寫作過程將一次寫入一行,因此您可能需要查看fgets()

+0

我猜'tail -f'不會改變任何東西,文件只會被其他進程修改。是的,'fgets()'會讓代碼更具可讀性,但是我必須檢查行結尾 – Tombart