2016-06-24 2 views
0

Я пытаюсь получить только fopen() и fseek(), чтобы получить конкретные строки кода (не только одна строка, мне нужно получить линию выше и ниже текущей линии поиска).PHP получить несколько конкретных строк, используя fseek

Чтобы улучшить производительность, я знаю, как получить определенную строку для поиска, а затем выйти. Если мне нужна строка 5, тогда ее нужно искать в 4 и 6.

Вот код для получения байтов каждой строки, а затем помещается в массив как строки как ключ и значение как байты в 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; 

Как слить эти строки?

Примечание: я не хочу использовать splFileInfo или любые трюки, подобные массивам. Просто хочу найти выход.

+0

ли вы проверить версию PHP? Эта функция работает на PHP 4, PHP 5, PHP 7 –

ответ

0

Я создал функцию, которая читает файл и подсчитывает строки и хранит в массивах каждую строку байтов для поиска. Если задано максимальное значение, заданное linenum, оно будет ломаться от времени, чтобы сохранить производительность, чем в новой функции цикла, чтобы искать позицию в байтах, чтобы получить содержимое файла.

Я считаю, что эта функция может улучшиться.

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; 
} 

Результаты испытаний (1,3 Гб файлы, 100000000 строки кодов, стремятся 300000 линий кода):

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 
Смежные вопросы