我正在使用当前代码读取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(),但我不知道如何在这里实现它。
你能帮忙吗?
答案 0 :(得分:3)
可以使用
规避时间ignore_user_abort(true);
set_time_limit(0);
当遇到内存限制问题时,退一步看看你正在对你正在处理的数据做些什么可能是明智之举。您是否将数据推送到数据库中?从数据中计算出某些东西,但不需要存储实际数据......
你真的需要将行(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>";