Сбой PHP LimitIterator ("Не поддерживает поиск" + "Невозможно перемотать файл")

Я использую SplFileObject а также LimitIterator читать содержимое с позиции х до у большого файла.

Это прекрасно работает при использовании пути к файлу, как /home/devel/stuff/myfile.log,

При использовании пути, как http://mydomain.com:8090/devel/stuff/myfile.log это не работает. Путь правильный однако.

Это терпит неудачу при использовании абсолютных путей?


Сообщения об ошибках:

PHP Warning: SplFileObject::rewind() [<a href='splfileobject.rewind'>splfileobject.rewind</a>]: stream does not support seeking in ...

PHP Fatal error: Uncaught exception 'RuntimeException' with message 'Cannot rewind file ...'


Полный код:

  // $pStrFile contains the valid (yes!) path
  $oFile = new SplFileObject($pStrFile);
  // $nFrom = 80 and $nLines = 30
  $fileIterator = new LimitIterator($oFile, $nFrom, $nLines);

  foreach($fileIterator as $line) {
      $strLines .= $line;
  }

2 ответа

Решение

Это ограничение http-оболочки. Если файл находится на диске, вы можете получить к нему доступ в любой позиции. Если вы хотите начать чтение с середины файла, это возможно. Однако, когда файл находится на веб-сервере, и вы получаете его по HTTP, немного труднее прочитать середину файла.

Вы можете скопировать файл во временную папку, а затем использовать LimitIterator на нем.

Иметь rewind() функция работы на SplFileObject базовый streamwrapper должен поддерживать поиск.

Текущая оболочка HTTP потока PHP не поддерживает поиск. Таким образом, вы получаете сообщение об ошибке:

Предупреждение PHP: SplFileObject::rewind() [splfileobject.rewind]: поток не поддерживает поиск в...

Первой идеей, которая пришла мне в голову, было использование NoRewindIterator это просто отключает rewind() вызов и, следовательно, предотвращает запуск ошибки.

$obj      = new SplFileObject('http://www.stackru.com/');
$norewind = new NoRewindIterator($obj);
$limit    = new LimitIterator($norewind, 80, 30);

Однако, как нет rewind() больше, LimitIterator тоже немного одурачен. Это приводит к игнорированию параметра смещения, это будет не смещение 80, а просто ноль (без смещения).

Чтобы преодолеть это, CachingIterator можно вставить в микс. Это решает именно эту проблему:

$obj      = new SplFileObject('http://www.stackru.com/');
$norewind = new NoRewindIterator($obj);
$caching  = new CachingIterator($norewind);
$limit    = new LimitIterator($caching, 80, 30);

foreach ($limit as $i => $line)
{
    printf("%03d: %s", $i, $line);
 }

Пример вывода ( Демо):

080: 
081: </span>
082:                 </div>
083:                 <div id="hsearch">
084:                     <form id="search" action="/search" method="get" autocomplete="off">
085:                     <div>

Как вы можете видеть, технически PHPs SPL поставляется с достаточным количеством внутренних инструментов для резервирования записи во временный файл для потока HTTP. Но имейте в виду, что итератор здесь только вперед, а это значит, что вы можете использовать его только один раз.

Другие вопросы по тегам