【问题标题】:PHP Get X Amount of Lines from File until DonePHP 从文件中获取 X 行直到完成
【发布时间】:2018-08-17 14:42:45
【问题描述】:

我有一个包含 2000 行的文本文件,需要在连续循环中一次获取 100 行。我可以让它工作,但我必须手动更改每个 100 块的 $i 值。这是代码:

    $file = 'postcode_2000.txt';
    for ($i = 0; $i <= 99; $i++) {

        $str = str_replace(PHP_EOL, '', $file[$i]);
        $list[] = $str;

    }

    $list_json = json_encode($list);

我如何迭代这个每次获得下一个 100?

【问题讨论】:

  • 你不能使用array_chunk() 之类的东西将你的大数组分成更小的部分吗?

标签: php arrays file


【解决方案1】:

将文件放入数组后,您可以使用array_chunk()。先将file读入一个数组:

$lines = 'postcode_2000.txt';

然后将chunk文件分成100行部分:

$chunks = array_chunk($lines, 100, true); // true keeps a set of consecutive line numbers

输出将是这样的:

Array
(
    [0] => Array
        (
            [0] => line in file
            [1] => line in file
            [2] => line in file
            [3] => line in file
            [4] => line in file
            ...
            [94] => line in file
            [95] => line in file
            [96] => line in file
            [97] => line in file
            [98] => line in file
            [99] => line in file
        )

    [1] => Array
        (
            [100] => line in file
            [101] => line in file
            [102] => line in file
            [103] => line in file
            [104] => line in file
            ...
            [194] => line in file
            [195] => line in file
            [196] => line in file
            [197] => line in file
            [198] => line in file
            [199] => line in file
        )

    [2] => Array
        (
            [200] => line in file
            [201] => line in file
            [202] => line in file
            [203] => line in file
            [204] => line in file
            ...
            [294] => line in file
            [295] => line in file
            [296] => line in file
            [297] => line in file
            [298] => line in file
            [299] => line in file
        )
    ...    
    [18] => Array
        (
            [1800] => line in file
            [1801] => line in file
            [1802] => line in file
            [1803] => line in file
            [1804] => line in file
            ...
            [1894] => line in file
            [1895] => line in file
            [1896] => line in file
            [1897] => line in file
            [1898] => line in file
            [1899] => line in file
        )

    [19] => Array
        (
            [1900] => line in file
            [1901] => line in file
            [1902] => line in file
            [1903] => line in file
            [1904] => line in file
            ...
            [1994] => line in file
            [1995] => line in file
            [1996] => line in file
            [1997] => line in file
            [1998] => line in file
            [1999] => line in file
        )

)

【讨论】:

    【解决方案2】:

    如果你真的想使用循环而不是 array_chunk :)

    <?php
    
    $file = file('/tmp/postcodes_2000.txt');
    
    $list = array();
    $line_count = count($file);
    $chunk_size = 100;
    $current_line = 0;
    echo "Line count: ${line_count}" . PHP_EOL;
    while( $current_line < $line_count ) {
      $i = 0;
      $chunk = array();
      while($i < $chunk_size) {
        $str = str_replace(PHP_EOL, '', $file[$current_line]);
        $chunk[] = $str;
        echo "> Line ${current_line} : " . $file[$current_line] . PHP_EOL;
        $i++;
        $current_line++;
      }
      $list[] = $chunk;
    }
    
    $list_json = json_encode($list);
    echo $list_json . PHP_EOL;
    

    【讨论】:

    • 您的代码打印出一个包含 2000 行的单个数组,并且不会分块任何内容。
    • 对不起,由于某种原因是旧代码,刚刚更新了答案
    • 忽略我最后的评论,我在测试中打错了你的代码
    【解决方案3】:

    当您计算大型集合并且不想同时为所有结果分配内存或不知道是否需要所有结果时,生成器非常有用,因为以处理结果的方式,通过仅为当前结果分配内存,可以将内存占用减少到最低限度。

    所以这是一种非常快速的方式,消耗更少的内存来实现您的目标:

    我们打开文件,读取精确数量的行,然后产生结果,同时保持下一次迭代的状态,从而使您能够非常快速地处理块并减少内存消耗。

    这样做的好处是避免读取所有文件两次以构建块(读取一次以构建包含所有行的大数组,然后循环遍历该数组以构建块),然后最终允许您(第三time) 循环遍历块数组...

    function file_get_x_lines($file,$amount=100){
        if(!file_exists($file)||!is_file($file)||!is_readable($file))
            return;
        if(!is_int($amount)||$amount<1) $amount=1;
        $handle=fopen($file,'rb');
            $i=0;
            while($line=fgets($handle)){
                if($i===0)
                    $tmp=array();
                $chunks[]=rtrim($line,PHP_EOL);
                $i++;
                if($i===$amount){
                    $i=0;
                    $tmp=$chunks;
                    $chunks=array();
                    yield $tmp;
                }
            }
            if(!$line)
                yield $chunks; 
    
        }
    

    然后你可以像使用任何生成器一样使用它

    foreach(file_get_x_lines(__FILE__) as $list)    {
        $list=json_encode($list);
        //do stuff
    }
    

    如果你想保持与行号相同的键,你可以这样轻轻地改变函数:

    function file_get_x_lines($file,$amount=100){
            if(!file_exists($file)||!is_file($file)||!is_readable($file))
                return;
            if(!is_int($amount)||$amount<1) $amount=1;
            $handle=fopen($file,'rb');
                $i=0;
                $j=1;
                while($line=fgets($handle)){
                    if($i===0)
                         $tmp=array();
                    $chunks[$j]=rtrim($line,PHP_EOL);
                    $i++;
                    $j++;
                    if($i===$amount){
                        $i=0;
                        $tmp=$chunks;
                        $chunks=array();
                        yield $tmp;
                    }
                }
                if(!$line)
                    yield $chunks; 
    
    }
    

    【讨论】:

    • 如何减少内存消耗?
    • @jayBlanchard 你认为这会消耗更多内存吗?
    • 你说它使用更少的内存,所以我只是想知道它是如何使用更少的内存的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-04
    • 1970-01-01
    相关资源
    最近更新 更多