PHPでCSVファイルの読み込み

PHP
スポンサーリンク

CSVファイルの読み込み

.csvファイルは、「,」等の区切り文字で区切られたデータファイルの事です。

リンゴ,バナナ,みかん

区切り文字は、一般的に半角カンマやスペース等が使われるが特に決まっていないので好きな物を指定出来ます。

エクセルデータやデータベース用のデータを他のプログラムからも扱える様に汎用化したもので、10万行を超えるデータも有りますので今回は処理スピードも調べて見たいと思います。

今回は、郵便番号全国一括データ(1,691,022Byte)を読み込んでタイムを計ります。

SplFileObjectを使う場合

非常に簡単簡潔に書けるので使っている人も多いと思います。
個人レベルで使うデータを扱う場合はお手軽で良いかもしれません。

<?php
$path = "./zip/KEN_ALL.CSV";
$file = new SplFileObject($path);
$file->setFlags(SplFileObject::READ_CSV);
$st = microtime(true);
$i = 1;
foreach ($file as $line) {
  $i++;
}
echo $i . "件終了<br />";
$end = microtime(true);
echo '処理時間:'.($end - $st)."秒<br />";
124521件終了
処理時間:0.83268404006958

fgetcsvを使う場合

<?php
$path = "./zip/KEN_ALL.CSV";
$fh = @fopen($path, "r");
echo "csvtest<br />";
$st = microtime(true);
if(!$fh){
  echo "error";
}else{
  $i = 1;
  while (!feof($fh) && ($line = fgetcsv($fh))) {
    $i++;
  }
  fclose($fh);
  echo $i . "件終了<br />";
}
$end = microtime(true);
echo '処理時間:'.($end - $st)."秒<br />";
124520件終了
処理時間:0.81908202171326
@fopen
の「@」はエラー制御演算子でエラーが出ても(ファイルが開けなくても)そのままプログラムを追行します。「try catch」より簡単です。
・多少遅くなります。

stream_get_line + explodeを使う場合

<?php
$path = "./zip/KEN_ALL.CSV";
$fh = @fopen($path, "r");
echo "csvtest<br />";
$st = microtime(true);
if(!$fh){
  echo "error";
}else{
  while (!feof($fh)) {
    $line = stream_get_line($fh, 1024, "\n");
    if($line !== false){
      $dat = explode(",",$line);
      $i++;
    }
  }
  fclose($fh);
  echo $i . "件終了<br />";
}
$end = microtime(true);
echo '処理時間:'.($end - $st)."秒<br />";
124520件終了
処理時間:0.064127922058105(最速)
stream_get_line + explode
stream_get_line
・fgetsより早いとマニュアルに書いて有ったので使って見ました。
explode
・この組み合わせがダントツに早いみたいです。
次のpreg_splitexplodeでスピードが大分変わります。

stream_get_line + preg_splitを使う場合

<?php
$path = "./zip/KEN_ALL.CSV";
$fh = @fopen($path, "r");
$st = microtime(true);
if(!$fh){
  echo "error<br />";
}else{
  $i = 1;
  while (!feof($fh)) {
    $line = stream_get_line($fh, 1024, "\n");
    if($line !== false){
      $dat = preg_split("/[,]/",$line);
      $i++;
    }
  }
  fclose($fh);
  echo $i . "件終了<br />";
}
$end = microtime(true);
echo '処理時間:'.($end - $st)."秒<br />";
124520件終了
処理時間:0.20877385139465
stream_get_line + preg_split
stream_get_line
・fgetsより早いとマニュアルに書いて有ったので使って見ました。
preg_split
・split関数が削除になったのでその代わりです。
区切り文字を正規表現で指定出来ます。
・”/[\s,]/“とすればスペースとカンマに対応出来ます。

fgets + explodeを使う場合

<?php
$path = "./zip/KEN_ALL.CSV";
$fh = @fopen($path, "r");
$st = microtime(true);
if(!$fh){
  echo "error<br />";
}else{
  $i = 1;
  while (!feof($fh) && ($line = fgets($fh, 1024)) !== false) {
    $dat = explode(",",$line);
    $i++;
  }
  fclose($fh);
  echo $i . "件終了<br />";
}
$now = microtime(true);
echo '処理時間:'.($now - $st)."秒<br />";
124520件終了
処理時間:0.070059061050415
fgets
・stream_get_lineの方が早いかと思いきや全く変わりませんでした。(誤差)

まとめ

少量のデータを扱う場合は、メモリに一気に読み込むSplFileObjectを使っても良いかもしれませんが、大量のデータを扱う場合は、stream_get_lineやfgetsを使った方が良いみたいです。

また、preg_splitは正規表現を使えるので細かい指定が出来ますが、explodeとのスピード差が有るのでexplodeを使う方が良いでしょう。

タイトルとURLをコピーしました