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);
ファイル入出力を行う際は「ファイルの内容を読み込みモードで開き、一旦変数に読み出す。その後ファイルを書き込みモードで開き、一気に書き込む」に統一してみる。
続く。