PHP LimitIterator fails (“Does not support seeking” + “Cannot rewind file”)

血红的双手。 提交于 2019-12-23 03:12:57

问题


I use SplFileObject and LimitIterator to read content from position x till y of a big file.

This works perfectly when using a file path like /home/devel/stuff/myfile.log.

When using a path like http://mydomain.com:8090/devel/stuff/myfile.log it does not work. The path is correct however.

Does this fail when using absolute paths?


The error messages are:

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 ...'


Full code:

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

回答1:


This is a limitation of the http wrapper. If a file is on the disk, you can access it on any position. If you want to start reading in the middle of the file, that is possible. However, when the file is on a webserver and you get it with HTTP, it is a little bit harder to read the middle of the file.

You can copy the file to a temporary location and then use the LimitIterator on it.




回答2:


To have the rewind() function work on SplFileObject, the underlying streamwrapper needs to support seeking.

PHPs current HTTP stream wrapper does not support seeking. So you get the error message:

PHP Warning: SplFileObject::rewind() [splfileobject.rewind]: stream does not support seeking in ...

A first idea that came into my mind was to use the NoRewindIterator that just disables the rewind() call and therefore prevents triggering the error.

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

However, as there is no rewind() any longer, the LimitIterator is somewhat fooled, too. That results in ignoring the offset parameter, it would not be the offset of 80 but just of zero (no offset).

To overcome this, a CachingIterator can be inserted into the mix. It solves exactly that problem:

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

Example output (Demo):

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

As you can see, technically PHPs SPL ships with enough internal tools to spare writing to a temporary file for the HTTP stream. But please keep in mind, that the iterator here is forward only, meaning that you only can use it once.



来源:https://stackoverflow.com/questions/11309190/php-limititerator-fails-does-not-support-seeking-cannot-rewind-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!