0

制御できないかなり大きなcsvファイル(少なくともWeb用)があります。約10万行あり、大きくなるだけです。

Drupal Module Feedsを使用して、このデータに基づいてノードを作成しています。それらのパーサーは、50行のグループに解析をバッチ処理します。ただし、パーサーは引用符を適切に処理せず、csvファイルの約60%を解析できません。fgetcsvは機能しますが、私が知る限り、バッチ処理は行いません。

fgetcsvを使用してファイル全体を読み取ろうとすると、PHPは最終的にメモリを使い果たします。したがって、私は物事をより小さなチャンクに分割できるようにしたいと思います。これは可能ですか?

4

3 に答える 3

2

fgetcsv()指定されたファイルポインタから一度に1行ずつ読み取ることで機能します。PHPのメモリが不足している場合は、ファイル全体を一度に解析して、すべてを巨大な配列に入れようとしている可能性があります。解決策は、大きな配列に格納せずに1行ずつ処理することです。

バッチ処理の質問に直接答えるには、ファイルからn行を読み取り、を使用ftell()してファイル内で終了した場所を見つけます。この点をメモしておくと、fseek()前に呼び出すことで、将来のある時点でその点に戻ることができますfgetcsv()

于 2011-01-03T17:32:01.823 に答える
2

さて、一連の行を解析する関数を作成します。

function parseLines(array $lines) {
    foreach ($lines as $line) {
        //insert line into new node
    }
}

次に、それをバッチ処理します。

$numberOfLinesToBatch = 50;
$f = fopen($file, 'r');
if (!$f) die('implement better error checking');

$buffer = array();
while ($row = fgetcsv($f)) {
    $buffer[] = $row;
    if (count($buffer) >= $numberOfLinesToBatch) {
        parseLines($buffer);
        $buffer = array();
    }
}
if (!empty($buffer)) {
    parseLines(buffer);
}

fclose($f);

データをストリーミングし、変数を微調整することでバッファリングする行数を調整できます...

于 2011-01-03T17:36:59.453 に答える
0

問題は、CSVファイルをディスクから読み取る方法ではなく、メモリに保存している情報が多すぎることだと思います。(つまり、fgetcsvは一度に1行しか読み取らないため、1行分のデータが原因でメモリが不足している場合は、問題が発生します。)

そのため、次のようなアプローチを使用する必要があります。

  1. 'x'行を配列に読み込みます。
  2. この情報を処理する
  3. 一時変数/配列をすべてクリアします。
  4. FEOFまで繰り返します。

または、コマンドラインバージョンのPHPを介してCSV処理を実行し、メモリ制限がはるかに大きいカスタムphp.iniを使用することもできます。

于 2011-01-03T17:27:27.970 に答える