Я использую SplFileObject
и LimitIterator
для чтения содержимого с позиции x до y большого файла.
Это отлично работает при использовании пути к файлу, например /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; }
Это ограничение оболочки http. Если файл находится на диске, вы можете получить доступ к нему в любой позиции. Если вы хотите начать чтение в середине файла, это возможно. Однако, когда файл находится на веб-сервере, и вы получаете его с помощью HTTP, немного сложнее прочитать середину файла.
Вы можете скопировать файл во временное место, а затем использовать LimitIterator.
Чтобы функция SplFileObject
rewind()
работала над SplFileObject
, базовому потоковому потоку необходимо поддерживать поиск.
Текущая HTTP-оболочка PHP не поддерживает поиск. Таким образом, вы получите сообщение об ошибке:
PHP Предупреждение: SplFileObject :: rewind () [splfileobject.rewind]: поток не поддерживает поиск в …
Первой мыслью, которая пришла мне в голову, было использование NoRewindIterator
который просто отключает вызов NoRewindIterator
rewind()
и, следовательно, предотвращает запуск ошибки.
$obj = new SplFileObject('http://www.stackoverflow.com/'); $norewind = new NoRewindIterator($obj); $limit = new LimitIterator($norewind, 80, 30);
Однако, поскольку rewind()
больше не существует, LimitIterator
несколько обманут. Это приводит к игнорированию параметра смещения , это не будет смещение 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>
Как вы можете видеть, технически PHPs SPL поставляется с достаточным количеством внутренних инструментов, чтобы записывать временный файл для потока HTTP. Но имейте в виду, что итератор здесь только вперед, а это значит, что вы можете использовать его только один раз.