2010-08-11 88 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