エントリー

PHPでファイル入出力

ファイル入出力と排他処理のメモ。

主にこのあたりを読んでみて、結局のところどうやってロックするか。すごく今更ですが、PHPからはデータベースばかり使っていたので自分用にメモしておきます。あくまでもメモであって、上の内容のまとめとかでは無いです。ツッコミは歓迎。

data.txt に、1行を1件として処理番号と処理時間を記録していくとする。具体的には以下のようなデータファイルを扱うとする。(<tab> の部分はタブが入る。)

4<tab>17:02:08
3<tab>16:53:20
2<tab>16:43:03
1<tab>16:42:02

データの破損を避けるために、ファイル入出力の際はロック処理を行う。

$fp = fopen('data.txt', 'r+') or exit('error!');
flock($fp, LOCK_EX); //有効なロック
fwrite($fp, '追記したいデータ');
flock($fp, LOCK_UN);
fclose($fp);

ただし、'r+' だとファイルの内容がクリアされないので、文章を編集したり一行削除したりする場合には利用できない(以前の内容がファイル内に残ってしまう可能性がある。)
つまり「ファイルサイズが増えることがあっても減ることはない」という場合は 'r+' でのロックは有効だが、「ファイルの内容が減る可能性がある」という場合には使えない。

このような場合には 'w' でオープンすると、以前の内容がクリアされる。ただし、ロック方法に注意する。

$fp = fopen('data.txt', 'w') or exit('error!');
flock($fp, LOCK_EX); //fopenの時点でファイルがクリアされるので、このロックは無意味
fwrite($fp, '書き込みたいデータ');
flock($fp, LOCK_UN);
fclose($fp);

この処理はロックができていないけど、ロック処理の例としてこのコードが紹介されていることは多い気がする…。

で、'w' を使う場合の、定番のロック方法は無いっぽい。
処理方法を色々変えるのもヤヤコシイので、入出力を行うファイル自体にはロックを行わず、ロック専用ファイルを用意した方が良さそう。

以下の自作関数で、ファイルロックを行う。

function file_lock() {
  $fp = fopen('lock.txt', 'w') or exit('error!');
  flock($fp, LOCK_EX);
  return $fp;
}

function file_unlock($fp) {
  flock($fp, LOCK_UN);
  fclose($fp);
}

file_lock() でロックを行い、file_unlock() でロックを解除する。つまり、ファイルロック用に lock.txt を用意し、このファイルに排他処理を行う。実際に読み書きするファイルにはロックを行わない。(排他ロック中は他のプロセスが割り込めないので、ロックは1つかければ十分。)

具体的には以下のような流れで処理する。

$lp = file_lock();

~ここでファイルの読み書き~

file_unlock($lp);

ファイル入出力を行う際は「ファイルの内容を読み込みモードで開き、一旦変数に読み出す。その後ファイルを書き込みモードで開き、一気に書き込む」に統一してみる。

続く

ページ移動

ユーティリティ

カテゴリー

検索

エントリー検索フォーム
キーワード

過去ログ

過去ログ表示フォーム
キーワード

Feed