[PHP]fopenを使った行数を取得する独自関数fline()

Read More

ファイルの行数を取得したいときがある。


ファイルの行数を取得する方法でまっさきに思いつくのはfile()を使ったものだと思う。

■file()を使った行数の取得
<?php
$count = count(file({ファイルパス}));
echo $count;
?>



しかし、このあと同じファイルに対してfopen()で開くことになった場合、
或いは既にfopen()で開いているファイルに対してfile()を使うことになった場合など、はっきりいってファイルの開き損だ。
同じファイルに対して2度3度ファイルを開くことにどうしても無駄を感じてしまう。

つまり、同じファイルポインタを使って一度のファイルオープンで全てを済ませたい


そこでファイルポインタを使って行数を取得する関数を作ってみた。


■ファイルポインタを使ったファイルの行数を取得する独自関数fline()
<?php
/**
 * ファイルポインタを使ってファイルの行数の取得する
 * ****************************************40
 * 最終行の値が空文字の時その行はカウントしない。
 * rewind()は関数内では行わない。
 * 001 - 2013/05/24 xirasaya
 * @param resource &$fp // ファイルポインタ
 * @return integer // 行数
 */
function fline(&$fp) {
  for($total=0; fgets($fp); $total++);
  return $total;
}// end function
?>



この関数の使いどころはかなり限定されると思う。
なので一緒に利用例も載せておく。


事前に以下のようなcsvファイルを用意しておく。

■ファイル名:sample.csv
2013/05/20, "あいうえお"
2013/05/21, "かきくけこ"
2013/05/22, "さしすせそ"
2013/05/23, "たちつてと"
2013/05/24, "なにぬねの"


# 最終行の改行はあってもなくてもよい
# fputcsv()で作成されたcsvファイルと仮定した場合改行は入れておくのが正しい。
# なおfputcsv()はダブルクォートをつけてくれないので使うべきではない

このcsvファイルは毎日新しい情報をファイル末尾に追記していくものと仮定する。
つまり後ろに行くほど情報が新しい。


■利用例: csvファイルから新しい情報を3行取得する
ファイル名:fline.php
<?php
$fp = fopen('sample.csv', 'r');
$total = fline($fp);
rewind($fp);
$ary=array();
$cnt=0;
while($buf=fgetcsv($fp)) {
  if($total-$cnt<=3) {
    $ary[] = $buf;
  }// end if
  $cnt++;
}// end while
krsort($ary);
print_r($ary);					
?>


■結果
> array(
2 => array (0 => '2013/05/24', 1 => 'なにぬねの', ),
1 => array (0 => '2013/05/23', 1 => 'たちつてと', ),
0 => array (0 => '2013/05/22', 1 => 'さしすせそ',),
)


上記の例ではfline()の後でrewind()してファイルポインタの位置を調整している。
このように必要に応じてrewind()を加える必要がある。

またこのfline()を使うにあたって、当たり前だけどfopen()のオープンモードの挙動をきちんと知っている必要がある。


なお、上記の例と同様のことはfile()を使っても実装できると思う。
というかfile()を使った方がむしろもっとシンプルに書ける気がする。

しかしfile()は全てのファイルデータを配列に格納してしまうのに対して、こちらは指定した行のデータのみを格納できる。

メモリ管理の観点からみた場合、ファイルのデータが肥大してきた時にその違いを発揮するのではないかと思う。



まあ結局のところ全ては組み手次第。






--
と、ここまで書いて思ったけど、処理も一行で終わるなら別に関数にする必要もなかったかな