2013-02-20 54 views
1

因此,我正在爲自己做一個小實驗,這是一個用於讀取php錯誤日誌文件(使用SplFileObject)並在瀏覽器上輸出格式的腳本。SplFileObject將指針移至上一行

雖然這將是更多的邏輯來顯示它以相反的順序(最新的錯誤在上面)。 要使用「正常」順序,我只顯示每一行並調用$ file-> next();移動指針,但我周圍做它的其他方式,而且也沒有一個prev()previous()方法,據我所知,我發現的唯一方式是使用seek()

for($i = $lines_total - $start_at; $i > $lines_total - $start_at - $lines_to_get; $i--){ 
    $content->seek($i); 
    $data = $content->current(); 
    if(empty($data)){ 
     continue; 
    } 
} 

但是,這是令人難以置信的緩慢(一個16mb文件約7秒)。如果我按照正常的順序來做,它是瞬間的。

有誰知道任何方法?或者我想要做的是瘋狂的? xD我只是一個被迫編碼的設計師,所以我不太熟悉指針和類似的東西。

回答

1

如果有人遇到在我想出了一個非常簡單的解決方案的未來這個問題:

//get to the last position of the file and get the pointer position. 
$content->seek($content->getSize()); 
$lines_total = $content->key(); 
$byte = $content->ftell(); 

//all the line in the php error log starts like: [21-Feb-2013 22:34:53 UTC] so... 
$pattern = '/^\[.*\]/'; 

for(...){ 
//get the current output to preg_match it 
    $data = $content->current(); 

//go backward each time it doesnt match a line's start 
    while (preg_match($pattern, $data) === 0){ 
    $byte--; 
    $content->fseek($byte); 
    $data = $content->current(); 
    } 

//go backward 1 more position to start the next loop 
    $byte--; 
    $content->fseek($byte); 
} 

希望這可以幫助別人一天的xD

2

FROM PHP DOC

prev - 倒帶內部數組指針
prev()行爲就像next(),除了它迴繞內部數組指針一個地方,而不是前進它的。

正如你可以看到他們只能使用數組而不是文件指針....如果你想移動到下一行,你可以嘗試使用SplFileObject::ftell你只能使用這樣

$file = new SplFileObject("log.txt", "r"); 
$file = iterator_to_array($file); 

echo current($file), PHP_EOL; 
echo next($file), PHP_EOL; 
echo prev($file), PHP_EOL; 

拿到那麼前面的位置使用SplFileObject::fseek來實現你的反向...

$file = new ReverseableSplFileObject("log.txt", "r"); 
foreach ($file as $c) { 
    echo $c, PHP_EOL; 
} 
echo $file->prev(), PHP_EOL; 
echo $file->prev(), PHP_EOL; 
echo $file->prev(), PHP_EOL; 

輸出

A 
B 
C 
C 
B 
A 

修改的類

class ReverseableSplFileObject extends SplFileObject { 
    private $pos = array(); 

    function current() { 
     return trim(parent::current()); 
    } 

    function next() { 
     $this->eof() or $this->pos[] = $this->ftell(); 
     return parent::next(); 
    } 

    function prev() { 
     if (empty($this->pos)) { 
      $this->fseek(0); 
     } else { 
      $this->fseek(array_pop($this->pos)); 
     } 
     return $this->current(); 
    } 
} 
+0

謝謝,雖然我一直在研究一下,而且有人告訴我用數組來做會不會很好。我通過使用fseek的方式來解決這個問題。無論如何,謝謝你的幫助! :D – aleation 2013-02-21 12:57:48

+0

對於性能'fseek'比迭代器更快..請參閱http://stackoverflow.com/a/13421745/1226894 – Baba 2013-02-21 14:15:31

0

這是一個老問題,但使用SplFileObj最簡單的方法是使用密鑰,並尋求,

public function prev(){ 
    $key = $this->_splFileObj->key(); 
    if($key){ 
     --$key; 
    } 
    $this->_splFileObj->seek($key); 
} 

假設這種方法是圍繞SplFileObj包裝用的_splFileObj財產。