0

我正在使用当前代码读取 csv 文件并将其添加到数组中:

    echo "starting CSV import<br>";
    $current_row = 1; 
    $handle = fopen($csv, "r"); 
    while ( ($data = fgetcsv($handle, 10000, ",") ) !== FALSE ) 
    { 
        $number_of_fields = count($data); 
        if ($current_row == 1) { 
        //Header line 
            for ($c=0; $c < $number_of_fields; $c++) 
            { 
                $header_array[$c] = $data[$c]; 
            } 
        } else { 
        //Data line 
            for ($c=0; $c < $number_of_fields; $c++) 
            { 
                $data_array[$header_array[$c]] = $data[$c]; 
            } 

            array_push($products, $data_array);

        } 
        $current_row++; 
    } 
    fclose($handle); 
    echo "finished CSV import <br>";

但是,当使用非常大的 CSV 时,这会在服务器上超时,或者出现内存限制错误。

我想要一种分阶段进行的方法,所以在第一条说 100 行之后它将刷新页面,从第 101 行开始。

我可能会使用元刷新和 URL 参数来执行此操作。

我只需要知道如何调整上面的代码以从我告诉它的行开始。

我已经研究过 fseek() 但我不确定如何在这里实现它。

你能帮忙吗?

4

1 回答 1

3

可以使用来规避超时

ignore_user_abort(true);
set_time_limit(0);

当遇到内存限制问题时,明智的做法是退后一步,看看您实际上对正在处理的数据做了什么。您是否将数据推送到数据库中?根据数据计算一些东西,但不需要存储实际数据,……</p>

您真的需要将 ( array_push($products, $data_array);) 行推入一个数组(供以后处理)吗?你可以直接写入数据库吗?还是直接计算?或者直接构建一个html <table>?或者无论你当时在做什么,在while()循环中,没有先将所有东西都推入数组?

如果你能够分块处理,我猜你根本不需要那个数组。否则,您必须为每个块恢复数组 - 一点也不解决内存问题。

如果您可以设法更改处理算法以减少内存/时间浪费,那么您应该认真考虑任何需要往返浏览器的分块处理(出于许多性能和安全原因......)。

无论如何,您可以随时使用ftell()识别当前流偏移,并使用fseek()重新设置到该位置。您只需将该整数传递给您的下一次迭代。


也不需要你的内部for()循环。这应该产生相同的结果:

<?php

$products = array();
$cols = null;
$first = true; 

$handle = fopen($csv, "r"); 
while (($data = fgetcsv($handle, 10000, ",")) !== false)  { 
    if ($first) { 
        $cols = $data;
        $first = false;
    } else { 
        $products[] = array_combine($cols, $data);
    }
}

fclose($handle); 
echo "finished CSV import <br>";
于 2012-03-02T12:30:12.373 回答