2010-08-11 85 views
2

我有一個具有更改日誌的txt文件。我試圖僅顯示當前版本的新更改。如何開始使用PHP從指定行讀取txt文件?

我寫了一個函數來讀取文件,並檢查每一行是否有想要的單詞,如果它發現這些單詞開始獲取內容並將其推送到數組。

我搜索了一下,看看是否有例子,但是大家都在談論如何停在指定的行,而不是從一個開始。

這裏是我使用的代碼:

public function load($theFile, $beginPosition, $doubleCheck) { 

    // Open file (read-only) 
    $file = fopen($_SERVER['DOCUMENT_ROOT'] . '/home/' . $theFile, 'r'); 

    // Exit the function if the the file can't be opened 
    if (!$file) { 
     return; 
    } 

    $changes = Array(); 

    // While not at the End Of File 
    while (!feof($file)) { 

     // Read current line only 
     $line = fgets($file); 

     // This will check if the current line has the word we look for to start loading 
     $findBeginning = strpos($line, $beginPosition); 

     // Double check for the beginning 
     $beginningCheck = strpos($line, $doubleCheck); 

     // Once you find the beginning 
     if ($findBeginning !== false && $beginningCheck !== false) { 

      // Start storing the data to an array 
      while (!feof($file)) { 

       $line = fgets($file); 

       // Remove space and the first 2 charecters ('-' + one space) 
       $line = trim(substr($line, 2)); 

       if (!empty($line)) { // Don't add empty lines 
        array_push($changes, $line); 
       } 
      } 
     } 
    } 

    // Close the file to save resourses 
    fclose($file); 

    return $changes; 
} 

它的工作現在,但你可以看到它的嵌套循環,這就是不好的,萬一txt文件的增長將需要更多的時間!

我試圖改善性能,那麼有沒有更好的方法來做到這一點?

回答

4

比你想象的

$found = false; 
$changes = array(); 
foreach(file($fileName) as $line) 
    if($found) 
     $changes[] = $line; 
    else 
     $found = strpos($line, $whatever) !== false; 
+0

真的很棒,更簡單的代碼,並訣竅:D 我嘗試使用'file()'函數,但我錯了! 我注意到它需要更多的時間,但沒關係。我喜歡這種方法。謝謝! – Maher4Ever 2010-08-11 22:36:52

+0

請注意,藉此,您可以將整個文件有效地讀入內存。適用於小文件..但如果文件太大,最終可能會導致腳本死亡。特別是在繁忙的服務器上。 – cHao 2012-09-21 18:50:44

0

嵌套循環不會降低性能,因爲它不是一個真正的嵌套循環,因爲它是一個多變量組合生長循環。雖然沒有必要這樣寫。這是避免它的另一種方式。試試這個(這裏是僞代碼):

// skim through the beginning of the file, break upon finding the start 
// of the portion I care about. 
while (!feof($file)) { 
    if $line matches beginning marker, break; 
} 

// now read and process until the endmarker (or eof...) 
while (!feof($file)) { 
    if $line matches endmarker, break; 

    filter/process/store line here. 
} 

此外,doublechecking是絕對沒有必要的。那是爲什麼?

+0

在做的這樣簡單得多,將在第二的'$ line' while循環對應於當前行?我沒有這樣做,因爲我認爲如果你退出循環,標記會回到開始。找到開始。我使用該版本,然後仔細檢查日期。謝謝。 – Maher4Ever 2010-08-11 21:36:02

+0

@ Maher4Ever:不,沒有任何操作將文件指針移回。 fopen()將它放在開頭,fgets將它移動一行。文件指針不知道該循環。 – 2010-08-11 22:57:10

+1

是的,在閱讀手冊之前我不應該問這個^^ !. 感謝您的解釋,無論如何:D – Maher4Ever 2010-08-11 23:09:58