当你需要处理一个5G的文件里面的数据时,你会怎么做,将文件里面的内容全部读取到一个数组里面去? 显然这种做法对小文件是没有问题的,但是对于大文件还是不行的 

这时就需要用到  yield 了 ,注意这是php5.5之后才有的

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

1.首先我们看一个基本的代码 

<?php
function aa($number){
for($i=0;$i<$number;$i++){
$data[] = $i.'-'.time();
}
return $data;
}

$result = aa(5);
foreach($result as $value){
sleep(1);//这里停顿1秒
echo $value.'<br />';
}

这是一个正常的代码,我们将传入的数据当做一个很大的数据(虽然目前是5),结果为

php 大文件读取 随笔 第1张
0-1555485328
1-1555485328
2-1555485328
3-1555485328
4-1555485328
View Code

(1)很明显,我们执行的循序是,先将for里面的全部执行完(因为时间戳都是一样的),然后再执行foreach这个函数。5条是没有问题的,但是如果是五百万条呢,会不会太大,占用太多资源

 

2.我们再看优化之后的 

<?php
function aa($number){
    for($i=0;$i<$number;$i++){
        yield $i.'-'.time();
    }
}

$result = aa(5);
foreach($result as $value){
    sleep(1);//这里停顿1秒
    echo $value.'<br />';
}

利用yield 返回数据,我们再看一下结果

php 大文件读取 随笔 第3张
0-1555485647
1-1555485648
2-1555485649
3-1555485650
4-1555485651
View Code

(2)我们可以发现,程序会先从for里面拿出一个值,然后利用这个值来进行foreach,当这次循环完了后,再自动去for里面取第二个值。可以发现,只是时间变了,结果内容完全是一样的

像这样一个值一个值的处理,不管你数据有多大,我始终只处理一个值。就很大程度上优化了代码 ,节约了资源

 

我们来运行一个实例,读取一个txt文件 

php 大文件读取 随笔 第5张
<?php
function read($path){
    $file = fopen($path, "r");
//输出文本中所有的行,直到文件结束为止。
    while(! feof($file))
    {
        yield fgets($file)."<br>";//fgets()函数从文件指针中读取一行
    }
    fclose($file);
}

$a = read('test.txt');
foreach ($a as $val){
    echo $val;
}
View Code

输出:

php 大文件读取 随笔 第7张
第1行 
第2行 
第3行 
第4行 
第5行 
第6行 
第7行 
第8行 
第9行 
第10行 
第11行
View Code

 

输出的结果和没用yiled是一样的,看不出来,我们加一个时间戳,并停顿一秒试一下

a, 不用yield 

php 大文件读取 随笔 第9张
<?php
function read($path){
    $file = fopen($path, "r");
//输出文本中所有的行,直到文件结束为止。
    while(! feof($file))
    {
        $data[] = fgets($file).time()."<br>";//fgets()函数从文件指针中读取一行
    }
    return $data;
    fclose($file);
}

$a = read('test.txt');
foreach ($a as $val){
    sleep(1);
    echo $val;
}
View Code

结果:

php 大文件读取 随笔 第11张
第1行 1555488162
第2行 1555488162
第3行 1555488162
第4行 1555488162
第5行 1555488162
第6行 1555488162
第7行 1555488162
第8行 1555488162
第9行 1555488162
第10行 1555488162
第11行1555488162
View Code

 

b.用yield

php 大文件读取 随笔 第13张
<?php
function read($path){
    $file = fopen($path, "r");
//输出文本中所有的行,直到文件结束为止。
    while(! feof($file))
    {
        yield fgets($file).time()."<br>";//fgets()函数从文件指针中读取一行
    }
    fclose($file);
}

$a = read('test.txt');
foreach ($a as $val){
    sleep(1);
    echo $val;
}
View Code

结果:

php 大文件读取 随笔 第15张
第1行 1555487737
第2行 1555487738
第3行 1555487739
第4行 1555487740
第5行 1555487741
第6行 1555487742
第7行 1555487743
第8行 1555487744
第9行 1555487745
第10行 1555487746
第11行1555487747
View Code

(3)发现虽然结果一样,但是他们的执行过程是不一样的。

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄