所以我正在为自己做一个小实验,一个脚本来读取php错误的日志文件(使用SplFileObject)并在浏览器上输出格式。
我虽然以相反的顺序显示它会更加逻辑(最新的错误在顶部)。
要使用“正常”顺序,我只显示每一行并调用$ file-> next();移动指针,但正如我在反过来做的那样,据我所知,没有prev()
或previous()
方法,我找到的唯一方法是使用{{1} }:
seek()
但这非常慢(对于16mb文件大约7秒)。如果我按照正常的顺序进行,那就是即时的。
有谁知道任何方法?或者我想做的是疯了吗? xD我只是一个被迫编写代码的设计师,所以我对指针和类似的东西不是很熟悉。
答案 0 :(得分:2)
来自PHP DOC
prev - 倒回内部数组指针
prev()的行为与next()类似,不同之处在于它将内部数组指针倒回一个位置,而不是将其推进。
正如您所看到的,它们只能使用数组而不是文件指针....您只能像这样使用它
$file = new SplFileObject("log.txt", "r");
$file = iterator_to_array($file);
echo current($file), PHP_EOL;
echo next($file), PHP_EOL;
echo prev($file), PHP_EOL;
如果您想转到下一行,可以尝试使用SplFileObject::ftell
获取之前的位置,然后使用SplFileObject::fseek
来实现您的反向...
示例
$file = new ReverseableSplFileObject("log.txt", "r");
foreach ( $file as $c ) {
echo $c, PHP_EOL;
}
echo $file->prev(), PHP_EOL;
echo $file->prev(), PHP_EOL;
echo $file->prev(), PHP_EOL;
输出
A
B
C
C
B
A
修改后的课程
class ReverseableSplFileObject extends SplFileObject {
private $pos = array();
function current() {
return trim(parent::current());
}
function next() {
$this->eof() or $this->pos[] = $this->ftell();
return parent::next();
}
function prev() {
if (empty($this->pos)) {
$this->fseek(0);
} else {
$this->fseek(array_pop($this->pos));
}
return $this->current();
}
}
答案 1 :(得分:2)
如果将来有人遇到这个问题,我想出了一个非常简单的解决方案:
//get to the last position of the file and get the pointer position.
$content->seek($content->getSize());
$lines_total = $content->key();
$byte = $content->ftell();
//all the line in the php error log starts like: [21-Feb-2013 22:34:53 UTC] so...
$pattern = '/^\[.*\]/';
for(...){
//get the current output to preg_match it
$data = $content->current();
//go backward each time it doesnt match a line's start
while ( preg_match( $pattern, $data ) === 0 ){
$byte--;
$content->fseek($byte);
$data = $content->current();
}
//go backward 1 more position to start the next loop
$byte--;
$content->fseek($byte);
}
希望有一天能帮助某人xD
答案 2 :(得分:0)
这是一个老问题但是使用SplFileObj最简单的方法是使用密钥并寻求,
public function prev(){
$key = $this->_splFileObj->key();
if( $key ){
--$key;
}
$this->_splFileObj->seek($key);
}
假设此方法位于SplFileObj的包装中,其属性为_splFileObj
。