QA@IT

PHPのfopenで行っているファイル処理を高速化したい

6866 PV

お世話になっております。

PHPで
ファイル1(タブ区切り)とファイル2(カンマ区切り)の2ファイルを比較し、
ファイル1のA列目とファイル2のA列目が一致したら
ファイル2のC列目の値をファイル1のC列に代入するといった処理を行っています。

$fp = fopen( ファイル1, 'r');
while($data = fgetcsv( $fp , 10000 ,"\t" )){
   for($i=0;$i<180;$i++){
          $new_data[$i] = $data[$i];//new_dataは出力用の配列
      }
   $fp2 = fopen( ファイル2, 'r');
   while($data2 = fgetcsv( $fp2 , 10000 ,"," )){
      if($data[0]==$data2[0]){
                  $new_data[2] = $data2[2];
        }
      }
   fclose($fp2);
   //出力処理関数呼び出し(この中で出力用ファイルに1行書き込む)
   csv_export('出力用ファイル名');
}
fclose($fp);

処理自体は問題なく行われるのですが、
ファイルが大きいため処理がかなり遅いです。
(ファイル1、2ともに6MB程度で4000行×180列程度のデータになります)

処理を高速化するにはどのような方法がありますでしょうか?

調べたところfgetcsvは処理が遅いとのことだったため、
ネストの中の処理をfgetsとexplodeを使った処理に変更してみましたが、
早くなったといっても微々たるものでした。

回答

fgetcsv が云々ではなくロジックが色々おかしいように見えます。


$data から $new_data へのコピーでわざわざループで回す必要があると思えません。$new_data = $data; でいいのでは?。

もしかしたら array をオブジェクト参照のように思われているのかもしれませんが PHP ではそうではありません。


ファイル1の fgetcsv のループの中で毎回ファイル2を開いてループで回す必要があると思えません。

ファイル2を事前に開いて array($col_1 => $col_3, ...) な連想配列を作っておけばループの中で毎回開く必要はありません。

ただし、その連想配列の分だけメモリを余分に食いますが。


csv_export の中で(恐らく)毎回 fopenfclose する必要があると思えません。

他2つと比べれば些細なものですが csv_export の中で fopenfclose するよりも、事前に fopen しておいたファイルにループの中で追記をする方がいいです。

編集 履歴 (0)
  • ご指摘ありがとうございました。
    根本的にいろいろ問題があったようで勉強になりました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。