zoukankan      html  css  js  c++  java
  • php 大文件读取 之 yield

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

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

    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),结果为

    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 返回数据,我们再看一下结果

    0-1555485647
    1-1555485648
    2-1555485649
    3-1555485650
    4-1555485651
    View Code

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

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

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

    <?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

    输出:

    第1行 
    第2行 
    第3行 
    第4行 
    第5行 
    第6行 
    第7行 
    第8行 
    第9行 
    第10行 
    第11行
    View Code

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

    a, 不用yield 

    <?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

    结果:

    第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
    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

    结果:

    第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)发现虽然结果一样,但是他们的执行过程是不一样的。

  • 相关阅读:
    【bzoj4917】Hash Killer IV 乱搞
    【bzoj2770】YY的Treap 权值线段树
    【bzoj4898】[Apio2017]商旅 Floyd+分数规划+Spfa
    【GXZ的原创】平衡树性能测试
    【bzoj2969】矩形粉刷 期望
    【bzoj3325】[Scoi2013]密码 逆模拟Manacher
    【bzoj4974】字符串大师 逆模拟KMP
    【bzoj4987】Tree 树形背包dp
    【bzoj3672】[Noi2014]购票 斜率优化dp+CDQ分治+树的点分治
    【bzoj4325】NOIP2015 斗地主(&“加强”版) 搜索
  • 原文地址:https://www.cnblogs.com/paopao123/p/10723860.html
Copyright © 2011-2022 走看看