fseek () строка, а не байты? - PullRequest
       18

fseek () строка, а не байты?

18 голосов
/ 28 августа 2010

У меня есть скрипт, который разбирает большие файлы построчно. Когда он обнаруживает ошибку, которую не может обработать, он останавливается, уведомляя нас о последней проанализированной строке.

Действительно ли это лучший / единственный способ поиска определенной строки в файле? (fseek() не может использоваться в моем случае.)

<?php

for ($i = 0; $i < 100000; $i++)
    fgets($fp); // just discard this

У меня нет проблем с этим, это достаточно быстро - просто немного грязно. Из того, что я знаю о базовом коде, я не думаю, что есть лучший способ сделать это.

Ответы [ 5 ]

35 голосов
/ 01 октября 2011

Простой способ поиска определенной строки в файле - использовать класс SplFileObject, который поддерживает поиск по номеру строки (seek()) или байтусмещение (fseek()).

$file = new SplFileObject('myfile.txt');
$file->seek(9999);     // Seek to line no. 10,000
echo $file->current(); // Print contents of that line

В фоновом режиме seek() просто делает то, что делал ваш PHP-код (за исключением кода C).

4 голосов
/ 28 августа 2010

Если у вас есть только номер строки, другого способа найти линию не существует. Файлы не основаны на строках (или даже на символах), поэтому невозможно просто перейти к определенной строке в файле.

Могут быть и другие способы чтения строк в файле, которые могут быть немного быстрее, например, чтение больших кусков файла в буфер и чтение строк из этого, но можно только надеяться, что это будет на несколько процентов быстрее , Любой способ найти определенную строку в файле все же должен прочитать все данные до этой строки.

2 голосов
/ 01 октября 2011

Я знаю, что уже поздно для публикации, но это может помочь некоторым людям. Я однажды сделал такую ​​функцию, как fseekbyline ...

function GoToLine($handle,$line)
{
  fseek($handle,0);  // seek to 0
  $i = 0;
  $bufcarac = 0;                    

  for($i = 1;$i<$line;$i++)
  {
    $ligne = fgets($handle);
    $bufcarac += strlen($ligne);  // in the end bufcarac will contains all caracters until the line
  }  

  fseek($handle,$bufcarac);
}

система ошибок отсутствует, если вы хотите перейти на строку <1 или 203, но файл пуст ... вы не получите ничего хорошего. </p>

то же самое, если вы хотите выйти из eot

1 голос
/ 22 июля 2014
rewind($handle);
while($i=0; $i<$desired_line; i++)
    fgetcsv($handle, 1000, ",")

Это работает для меня, в то время как мне нужно перематывать к определенной строке несколько раз в моем сценарии.

Я не уверен, съедает ли это память или скорость, но это помогает.

0 голосов
/ 28 августа 2010

Если я правильно понимаю, вы хотите перейти к определенной строке в какой-то момент после того, как обнаружите ошибку. Если это так, вы, вероятно, где-то сохраните или напечатаете номер строки плохой строки, в зависимости от того, что вы подразумеваете под «уведомить».

Если вы действительно не имеете в виду, что вы не можете использовать fseek()*, вы можете также сохранить / распечатать позицию в файле, где начинается плохая строка. Тогда вы можете fseek().

* Как, в таком случае, fseekbyline() можно было бы использовать, если бы оно существовало?

...