一个懒癌患者的自言自语



php低内存读取大文件大目录

1.逐行读取大文件

function readFileAll($path) {
    if ($handle = fopen($path'r')) {
        while (! feof($handle)) {
            yield trim(fgets($handle));
        }
        fclose($handle);
    }
}

读取处理

$data = readFileAll('robots.txt');
foreach($data as $v) {
    //处理.....
}

2.从指定行开始读取,读取指定长度

/**
 * 从指定行开始读取
 *
 * @param [type] $path     文件路径
 * @param [type] $count    读取多少行
 * @param integer $offset  从哪行开始读
 * @return void
 */
function readFileLine($path, $count = 0, $offset = 0) {
    $arr = [];
    if (!is_readable($path)) {
        return $arr;
    }
        
    $fp = new SplFileObject($path'r');
    
    // 定位到指定的行数开始读
    if ($offset) {
        $fp->seek($offset); 
    }
 
    $i = 0;
    
    while (!$fp->eof()) {
        $i++;
        // 只读 $count 这么多行
        if ($count > 0 && $i > $count) {
            break;
        }
            
        $arr[] = trim($fp->current());
 
        // 指向下一个
        $fp->next();
    }
    
    return $arr;
}

使用

$data = readFileLine('robots.txt'11);

以上例子主要都是使用到php的高级特性sql迭代器和生成器,关键字yield 返回的是生成器对象,并没有立即生成数组,文件再大也不会出现巨无霸数组的情况,内存消耗是低到可以忽略不计的几十 kb 级别,时间消耗也几乎只有循环消耗,同理,遍历大目录可以使用 php自身提供的RecursiveDirectoryIterator()函数实现,另外复制大文件的时候推荐使用文件流的形式进行复制,用到的函数stream_copy_to_stream()

About ME

about me

kevin

一个在it道路上蹒跚学步的人

心有多大,舞台就有多大,一直奔跑在自己的路上!

Contact ME