0

I am using the current code to read a csv file and add it to an array:

    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>";

However when using a very large CSV this times out on the server, or has a memory limit error.

I'd like a way to do it in stages, so after the first say 100 lines it will refresh the page, starting at line 101.

I will probably be doing this with a meta refresh and a URL parameter.

I just need to know how to adapt that code above to start at the line I tell it to.

I have looked into fseek() but I'm not sure how to implement this here.

Can you please help?

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 に答える