2009-08-11 60 views
1

我想從文本文件中讀取所有內容並進行回顯。但是在閱讀時可能會有更多的行寫入文本文件,所以我不希望腳本在到達文件末尾時退出,而是我不想永遠等待更多行。這可能在PHP?在php中阻止文件讀取?

+0

這取決於您所瞄準的功能類型。該腳本是否在來自瀏覽器的請求的上下文中執行?它是一個可以無限運行的CLI腳本嗎? – 2009-08-11 18:59:30

+0

這是一個PHP腳本,將從命令行或從Web服務器運行? – Wade 2009-08-11 19:01:59

+0

命令行腳本,但這有什麼關係? – Martin 2009-08-11 19:56:23

回答

0

我解決了它。

訣竅是使用fopen,當達到eof時,將光標移動到前一個位置並繼續從那裏讀取。

<?php 
$handle = fopen('text.txt', 'r'); 
$lastpos = 0; 
while(true){ 
    if (!feof($handle)){ 
     echo fread($handle,8192); 
     flush(); 
     $lastpos = ftell($handle); 
    }else{ 
     fseek($handle,$lastpos); 
    } 
} 
?> 

雖然仍然消耗很多的CPU,不知道如何解決這個問題。

+0

你正忙於循環,當然它會消耗所有的CPU。嘗試在'fseek'行之後添加'usleep(50000)'。這將睡眠50ms,這會*大大*降低您的CPU使用率,對延遲沒有顯着影響。要做得更好,你需要使用inotify(假設你在一個支持它的系統上)。 – derobert 2009-08-11 21:06:14

+0

是的,我知道這是因爲循環,睡着了,但我並不是真正的睡眠解決方案粉絲。雖然看起來好像是我一直在尋找的東西,但明天我會看看。 – Martin 2009-08-11 21:26:30

1

這只是一個猜測,但嘗試通過(passthru)「尾巴-f」輸出。

但你需要找到一種方法來flush()你的緩衝區。


恕我直言,更好的解決方案將是建立一個ajax網站。

將文件的內容讀入數組中。存儲會話中的行數。打印文件的內容。

每隔x秒向檢查文件的腳本啓動ajax請求,如果行數大於則會話計數將結果追加到頁面。


你可以使用POPEN()inststed:

$f = popen("tail -f /where/ever/your/file/is 2>&1", 'r'); 
while(!feof($f)) { 
    $buffer = fgets($f); 
    echo "$buffer\n"; 
    flush(); 
    sleep(1); 
} 
pclose($f) 

睡眠是很重要的,沒有它,你將有100%的CPU時間。

+0

其實我做了一個有效的尾部解決方案,但它使用了一個消耗所有cpu的無限循環,這就是爲什麼我需要某種「阻塞」調用。 每X秒呼叫是不夠的,我需要實時,它不是一個網站,所以沒有ajax。 – Martin 2009-08-11 19:04:50

+0

'tail -f'是「實時」的,完全不需要循環或php。 – VolkerK 2009-08-11 19:25:24

+0

那個popen-solution幾乎和我的一模一樣。問題在於睡眠,這使得延遲太大。 – Martin 2009-08-11 19:34:58

0

事實上,當你「回聲」它時,它會進入緩衝區。因此,如果在瀏覽器仍在接收輸出的情況下添加新內容,則需要「追加」新內容。這是不可能的(但有一些辦法)。

+0

你確實知道有flush()? – Rufinus 2009-08-11 20:20:19

0

你也可以使用filemtime:你得到最新的修改時間戳,發送輸出,並在最後比較存儲的filemtime與當前的一個。

無論如何,如果您希望腳本與瀏覽器(或客戶端)同時發送,則應使用塊(freadflush)發送輸出,然後檢查最後的任何更改。如果有任何更改,請重新打開文件並從最新位置讀取(您可以在while(!feof())的循環之外獲取位置)。