3

編集:Robusの回答に応えて、コマンドラインからPHPスクリプトを実行しようとしました。結果は次のとおりです。

CLIクラッシュ

しかし興味深いことに、コードのループのにあるechoステートメントは、そのテキストをコンソールウィンドウに出力します。foreachしたがって、スクリプトの実行の終了時または実行後にCLIがクラッシュすると想定することしかできません。


XLSXファイルからMySQLテーブルにすべての行をロードする関数であるスクリプトがあります。私はこれにPHPExcelを使用しています。loadFromXLSXLSXファイルからデータをロードし、データを含む2次元配列を返す関数を作成しました。この特定のケースでは、3100行29列を意味します。

これは機能です:

function loadFromXLS($filepath)
{
    $retval = array();
    $cols = array();
    $rownum = 0;

    $reader = PHPExcel_IOFactory::createReaderForFile($filepath);
    $reader->setReadDataOnly(true);

    $phpObject = $reader->load($filepath);
    $sheet = $phpObject->getActiveSheet();

    foreach($sheet->getRowIterator() as $row)
    {
        $celliterator = $row->getCellIterator();
        $celliterator->setIterateOnlyExistingCells(false);
        $cellnum = 0;

        foreach($celliterator as $cell)
        {
            if($rownum === 0)
            {
                $cols[$cellnum] = $cell->getValue();
            }
            else
            {
                if(is_array($retval[$rownum-1]))
                    $retval[$rownum-1] += array($cols[$cellnum] => $cell->getValue());
                else
                    $retval[$rownum-1] = array($cols[$cellnum] => $cell->getValue());
            }

            $cellnum++;
        }

        $rownum++;
    }

    unset($reader, $phpObject, $sheet);

    return $retval;
}

ファイルの一番上の行は列名です。

いずれにせよ、var_dump最初の数行を調べて配列の長さをチェックすることで、データが正しく読み込まれることを確認しました。

これが問題です。この行を追加するとすぐに:

foreach($data as $i => $row) {};

Apacheは、その時点に達すると単にクラッシュします。

Apacheのクラッシュ

それで、どうしたの?PHPは、大きな連想配列を介したループを処理できませんか?説明的な答えをいただければ幸いです。私が提供できる追加情報があればコメントしてください


XAMPPをWindows7、Intel i5プロセッサ、4GBRAMで実行しています。php.iniで512MBに増やしmemory_limitましたが、これで十分です(128MBに設定するとメモリエラーが発生していました)。このスクリプトには、PHPExcel.phpとdBug.phpが含まれています。2次元配列は文字列のみで埋められ、ファンキーなPHPExcelデータ型は埋められません。

PHPバージョン5.3.1を実行しています

ロードされたモジュール:コアmod_win32 mpm_winntでhttp_core mod_soはmod_actions mod_alias mod_asis mod_auth_basic mod_auth_digestをmod_authn_default mod_authn_fileでもmod_authz_default mod_authz_groupfile mod_authz_host mod_authz_user mod_cgiのmod_davのmod_dav_fs mod_dav_lockのmod_dir mod_envてmod_headersはmod_include mod_infoのmod_isapi mod_log_configのmod_mimeによりmod_negotiationのmod_rewrite mod_setenvifのmod_sslのmod_statusをmod_autoindex_color mod_php5 mod_perlのmod_apreq2

phpinfo()スクリーンショット

4

4 に答える 4

2

apache を完全に省略して、コマンド ラインからスクリプトを実行してみてください。何が起こるかを確認してください。

于 2011-04-17T18:12:35.500 に答える
1

PHP インストールを更新します。

于 2011-04-17T18:30:48.833 に答える
0
  1. PHPにメモリを追加します。

  2. PHPで大きな配列を返すのはそれほど幸運ではありません。代わりに使用する必要があります:

    function loadFromXLS($filepath,&$retval) {
      ...
    }
    

    次に、 $ retval = array();を削除する必要があります。そして、この機能の呼び出しの前にそれを置きます。

于 2011-04-17T19:45:26.017 に答える
0

$phpObject と $sheet を単純に設定解除しても、何の効果もありません。これらには循環オブジェクト参照が含まれており、これは PHP では適切にクリーンアップされないため、最初にそれらの参照を壊さない限り、設定が解除されません。これは、

$phpObject->disconnectWorksheets();

開発者ドキュメントのセクション 4.3 (「メモリからワークブックをクリアする」) で説明されているとおりです。

配列に値を設定するためのイテレータ ループを取り除き、PHPExcel の組み込みメソッドを使用します。

return $sheet->toArray(); 

次の引数を toArray() メソッドに渡すこともできます。

* @param  mixed    $nullValue            Value returned in the array entry if a cell doesn't exist
* @param  boolean  $calculateFormulas    Should formulas be calculated?
* @param  boolean  $formatData           Should formatting be applied to cell values?
* @param  boolean  $returnCellRef        False - Return a simple array of rows and columns indexed by number counting from zero
*                                        True - Return rows and columns indexed by their actual row and column IDs

独自のループが行う連想配列はまったく提供されませんが、ループよりも高速でメモリ効率が高くなります。

于 2011-04-17T21:06:09.063 に答える