2012-07-03 3 views
1

Я использую SplFileObject и LimitIterator для чтения содержимого с позиции x до y большого файла.Ошибка PHP 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; 
    } 

ответ

3

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

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

+0

Ну, это не то, что я искал, но это решение, которое в настоящее время работает. Благодарю. – Patrick

3

Для того, чтобы функция rewind() работала на SplFileObject, базовому потоковому потоку необходимо поддерживать поиск.

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

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

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

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

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

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

$obj  = new SplFileObject('http://www.stackoverflow.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); 
} 

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

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

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