谈到这两个功能的共通处就是都需要对大数据文件进行处理。
大数据文件处理
思想: php本身存在几个文件读取方法如file_get_content()和file()方法,的确这两个方法的处理速度速度快且容易使用,但由于php对内存的限制(php.ini memeory_limit=128M)而且一次性读取整个文件的可读性差(等待时间过长),因此需要一种大数据文件处理方法。php处理大数据文件的机制就是使用splfileObject类和yield生成器来定量一行行提取。
重点:
在上一次谈php读取文件IP地址就涉及到了对SplFileObject和yield生成器中的使用,这里只谈一下NoReWindIterator类。
php官网描述:This iterator ignores rewind operations. This allows processing an iterator in multiple partial foreach loops. (此迭代器忽略倒带操作。这允许在多个部分foreach循环中处理迭代器。 )
就我而言,这个类的作用就是一个得到的迭代器只能循环一次,后面多次循环不会得到任何结果。
后面就直接给代码了:
大数据文件处理类:
<?php
/*
* 遍历大数据文件:
* 使用yield生成器输出,不使用file_get_content和file()函数,使用SplFileObject类处理
* 三种遍历方式:逐行输出、定量输出、NoReWindIterator输出
*
* */
namespace Application\Iterator;
use Exception;
use InvalidArgumentException;
use SplFileObject;
use NoRewindIterator;
class LargeFile{
const ERROR_UNABLE = "ERROR:UNABLE TO OPEN THE FILE!";
const ERROR_TYPE = "ERROR:TYPE MUST BE 'ByLength','ByLine' or 'Csv'";
protected $file;
protected $allowTypes = ['ByLine','ByLength','Csv'];
//构造器初始化参数
function __construct($filename, $mode='r')
{
if(!file_exists($filename)){
$message = __METHOD__.':'.self::ERROR_UNABLE.PHP_EOL;
$message.= strip_tags($message);
throw new Exception($message);
}
$this->file = new SplFileObject($filename, $mode);
}
//逐行遍历
public function fileIteratorByLine(){
$count = 0; //统计行数
while(!$this->file->eof()){
yield $this->file->fgets(); //读取一行内容
$count++;
}
return $count;
}
//逐长度遍历,fread方法,protected类型方法,不能同时以两种方式遍历
protected function fileIteratorByLength($numBytes = 1024){
$count = 0;
while(!$this->file