2016-06-24 25 views
0

Ich versuche, nur fopen() und fseek() zu bekommen, um bestimmte Zeilen Code (nicht nur eine Zeile, ich brauche Linie über und unter der aktuellen Suchlinie) zu bekommen.PHP bekommen mehrere spezifische Zeile mit fseek

Um die Leistung zu verbessern, weiß ich, wie bestimmte Zeile zu suchen und dann zu beenden. Wenn ich Zeile 5 brauche, sollte in 4 und 6 gesucht werden.

Hier ist ein Code, um Bytes von jeder Zeile dann in Array als Zeilen als Schlüssel und Wert als Bytes zu EOF.

$fh = fopen($source, 'r'); 
$meta = stream_get_meta_data($fh); 

if (!$meta['seekable']) { 
    throw new Exception(sprintf("A source is not seekable: %s", print_r($source, true))); 
} 

$line = fgets($fh, 4096); 
$pos = -1; 
$i = 0; 

$result = null; 

$linenum = 10; 
var_dump('Line num:'.$linenum); 

$total_lines = null; 

// Get seek byte end of each line 
while (!feof($fh)) { 
    $char = fgetc($fh); 

    if ($char != "\n" && $char != "\r") {   
     $total_lines[$i] = $pos; 

     $pos++; 
    } else { 
     $i++; 
    }  
    //var_dump(fgets($fh).' _ '.$pos); 
} 

// Now get specific lines (line 5, line 6 and line 7) 
$seekssearch = array($total_lines[5], $total_lines[6], $total_lines[7]); 

$result = null; 
$posr = 0; 
foreach ($seekssearch as $sk) { 

    while (!feof($fh)) { 

     if ($char != "\n" && $char != "\r") { 

     fseek($fh, $sk, SEEK_SET); 

     $posr++; 

     } else { 
     $ir++; 


     } 
    } 

    // Merge result of line 5,6 and 7 
    $result .= fgets($fh);  
} 

echo $result; 






exit; 


while (!feof($fh) && $i<($linenum)) { 
      $char = fgetc($fh); 

      if ($char != "\n" && $char != "\r") { 
       fseek($fh, $pos, SEEK_SET); 
       $pos++; 

      } 
      else { 
       $i++; 
      } 
     } 
     $line = trim(fgets($fh)); 

     var_dump($line); 






exit; 




exit; 

while (!feof($fh) && $i<($linenum-1)) { 
    $char = fgetc($fh); 



    if ($char != "\n" && $char != "\r") { 
     //fseek($fh, $pos); 
     fseek($fh, $pos); 
     $pos++; 
    } 
    else { 

     if ($pos == 3) { 

      $line = fgets($fh); 
     } 

     $i++; 


    } 
} 

//$line = fgets($fh); 
var_dump($line); exit; 

Wie diese Zeilen zusammengeführt werden?

Hinweis: Ich möchte nicht splFileInfo oder irgendwelche Tricks wie Arrays verwenden. Ich möchte nur suchen und dann aussteigen.

+0

Haben überprüfen Sie die Version von PHP? Diese Funktion arbeitet mit PHP 4, PHP 5, PHP 7 –

Antwort

0

Ich habe eine Funktion erstellt, die eine Datei lesen und Zeilen zählen und speichern in Arrays jede Zeile Bytes zu suchen. Wenn das durch linenum festgelegte Maximum gesetzt ist, wird es unterbrochen, um die Leistung zu halten, als in einer neuen Schleifenfunktion, um eine Position in Bytes zu suchen, um einen Inhalt der Datei zu erhalten.

Ich glaube, dass diese Funktion verbessern kann.

function readFileSeek($source, $linenum = 0, $range = 0) 
{ 
    $fh = fopen($source, 'r'); 
    $meta = stream_get_meta_data($fh); 

    if (!$meta['seekable']) { 
     throw new Exception(sprintf("A source is not seekable: %s", print_r($source, true))); 
    } 

    $pos = 2; 
    $result = null; 

    if ($linenum) { 
     $minline = $linenum - $range - 1; 
     $maxline = $minline+$range+$range; 
    } 

    $totalLines = 0; 
    while (!feof($fh)) { 

     $char = fgetc($fh); 

     if ($char == "\n" || $char == "\r") { 
      ++$totalLines; 
     } else { 
      $result[$totalLines] = $pos; 
     } 
     $pos++; 

     if ($maxline+1 == $totalLines) { 
      // break from while to not read entire file 
      break; 
     } 
    } 

    $buffer = ''; 

    for ($nr=$minline; $nr<=$maxline; $nr++) { 

     if (isset($result[$nr])) { 

      fseek($fh, $result[$nr], SEEK_SET); 

      while (!feof($fh)) { 
       $char = fgetc($fh); 

       if ($char == "\n" || $char == "\r") { 
        $buffer .= $char; 
        break; 
       } else { 
        $buffer .= $char; 
       } 
      } 

     } 
    } 

    return $buffer; 
} 

Testergebnisse (1,3 GB-Datei, 100 Millionen Zeilen Code, suchen ein Code 300000 Linie):

string(55) "299998_abc 
299999_abc 
300000_abc 
300001_abc 
300002_abc 
" 


Time: 612 ms, Memory: 20.00Mb 

$ ll -h /tmp/testReadSourceLines_27151460344/41340913936 
-rw-rw-r-- 1 1,3G /tmp/testReadSourceLines_27151460344/41340913936