1

我使用SplFileObjectandLimitIterator从位置 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;
  }
4

2 回答 2

4

要使rewind()函数在 上工作SplFileObject,底层的流包装器需要支持查找。

PHP 当前的HTTP 流包装器不支持搜索。因此,您会收到错误消息:

PHP 警告:SplFileObject::rewind() [splfileobject.rewind]: 流不支持在 ...

我想到的第一个想法是使用NoRewindIterator只是禁用rewind()呼叫并因此防止触发错误的方法。

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

不过,既然没有了rewind(),那LimitIterator也有些上当了。这导致忽略偏移参数,它不会是 80 的偏移量,而只是零(无偏移量)。

为了克服这个问题,CachingIterator可以将 a 插入到混合物中。它正好解决了这个问题:

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

示例输出(演示):

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

正如您所看到的,从技术上讲,PHP SPL 附带了足够的内部工具,可以省去为 HTTP 流写入临时文件的时间。但是请记住,这里的迭代器是只向前的,这意味着你只能使用它一次。

于 2012-12-11T21:24:01.890 回答
3

这是 http 包装器的限制。如果文件在磁盘上,您可以在任何位置访问它。如果您想在文件中间开始阅读,这是可能的。但是,当文件位于网络服务器上并且您使用 HTTP 获取它时,读取文件中间会有点困难。

您可以将文件复制到临时位置,然后在其上使用 LimitIterator。

于 2012-07-03T10:43:26.417 回答