0

2 つの列を持つ 260k 行の csv ファイルがあります。fgetcsv を使用して csv ファイルを読み込んでおり、ファイル内のすべての行を読み取る while ループがあります。ループでは、2 番目の列の値を配列に追加しようとしています。

配列に追加する行があると、PHP がフリーズして終了しません。私はデバッグを行い、値が配列に追加されているので、配列への追加とwhileループが機能することはわかっていますが、フリーズする理由はわかりません。

行を削除すると、while ループが 260k 行を通過して完了し、残りのファイルが処理されます。

これが私のコードです:

$amountRecords = 0;
$totalValue = 0;
$valueArray = array();

// reads in csv file
$handle = fopen('Task1-DataForMeanMedianMode.csv', 'r');
// to skip the header names/values
fgetcsv($handle);

// creates array containing variables from csv file
while(($row = fgetcsv($handle, "\r")) != FALSE)
{

    /*
    echo "ROW CONTAINS: ";
    var_dump($row[1]);
    echo "<br />";
    */

    $valueArray[] = $row[1];

    /*
    echo "VALUEARRAY NOW CONTAINS: ";
    var_dump($valueArray);
    echo "<br />";
    */

    $totalValue = $totalValue + $row[1];
    $amountRecords++;

}

csv ファイルのサンプル:

ID,Value
1,243.00
2,243.00
3,243.00
4,243.00
5,123.11
6,243.00
7,180.00
8,55.00
9,243.00
10,55.00
4

4 に答える 4

1

メモリ不足エラーには、2 つの一般的なアプローチがあります。これらの選択肢ではいつものように、簡単だが間違っているものと難しいが正しいものを選ぶことができます。簡単だが間違った解決策は、メモリ制限を適切なレベルに引き上げることです。

ini_set('memory_limit', '64M');

より良い (より難しい) 解決策は、アルゴリズムを再設計してメモリをあまり必要としないようにすることです。これは明らかに、より持続可能で堅牢なアプローチです。これを適切に行うには、構築しているアレイで何をする必要があるかを評価する必要があります。たとえば、行をデータベースにインポートする同様のスクリプトを作成しました。巨大な配列を構築してから挿入する代わりに 50 ~ 100 行の配列を構築し、それらを挿入して配列をクリアしました (再利用のためにメモリを解放しました)。

擬似コード:

for(each row in file) {
  $rows_cache[] = $row[1];
  if(count($rows_cache) >= 50) {
    insert_these($rows_cache);
    $rows_cache = array();
  }
}
于 2012-08-19T19:48:34.440 に答える
0

最初の行は文字列です。追加してみてください

while(($row = fgetcsv($handle, "\r")) != FALSE)
{

    if(is_numeric($row[1]))
    { 
        $valueArray[] = $row[1];

        $totalValue = $totalValue + $row[1];
        $amountRecords++;
    }
}
于 2012-08-19T16:30:24.633 に答える
0

行をドロップしない理由:

$totalValue = $totalValue + $row[1];

ループ内から、代わりに次を使用します。

$totalValue = array_sum($valueArray);

ループを完了した後

于 2012-08-19T17:12:01.870 に答える
0

特に問題はありませんが、

while(($row = fgetcsv($handle, "\r")) != FALSE)

として書き換えることができます

while($row = fgetcsv(...)) 

代わりは。明示的な false チェックは必要ありません。fgetcsv が false を返した場合、while ループはとにかく終了します。さらに、このバージョンは読みやすく、リスクもありません。()fgetの周りを忘れる$row = (fgetcsv() != false)と、ブール値を取得するのと同等のことを行うことになります。

于 2012-08-19T17:14:02.587 に答える