記事表示
PHPでファイル入出力(続き)
この記事の続き。ファイル入出力の具体的なコード。
/* ファイルの先頭に追加 */
$no = 0;
$data = '';
$fp = fopen('data.txt', 'r') or exit('error!');
while ($line = fgets($fp)) {
if (intval($line) > $no) {
$no = intval($line);
}
$data .= $line;
}
fclose($fp);
$no++;
$fp = fopen('data.txt', 'w') or exit('error!');
fwrite($fp, "$no\t" . date('H:i:s') . "\n$data");
fclose($fp);/* ファイルの末尾に追加 */
$no = 0;
$data = '';
$fp = fopen('data.txt', 'r') or exit('error!');
while ($line = fgets($fp)) {
if (intval($line) > $no) {
$no = intval($line);
}
$data .= $line;
}
fclose($fp);
$no++;
$fp = fopen('data.txt', 'w') or exit('error!');
fwrite($fp, "$data$no\t" . date('H:i:s') . "\n");
fclose($fp);/* 任意の行を編集 */
$no = 3; //No.3のデータを編集
$data = '';
$fp = fopen('data.txt', 'r') or exit('error!');
while ($line = fgets($fp)) {
if (intval($line) == $no) {
$data .= "$no\t" . date('H:i:s') . "\n";
} else {
$data .= $line;
}
}
fclose($fp);
$fp = fopen('data.txt', 'w') or exit('error!');
fwrite($fp, $data);
fclose($fp);/* 任意の行を削除 */
$no = 3; //No.3のデータを削除
$data = '';
$fp = fopen('data.txt', 'r') or exit('error!');
while ($line = fgets($fp)) {
if (intval($line) != $no) {
$data .= $line;
}
}
fclose($fp);
$fp = fopen('data.txt', 'w') or exit('error!');
fwrite($fp, $data);
fclose($fp);でも、単にファイルの末尾にデータを追加し続ける場合は、'a+'を使って、ロックも自前で行ったほうが圧倒的に効率が良さそう。(この場合は、一時的にデータを保存する変数のために、無駄に巨大なメモリを消費する必要は無いので。)
/* ファイルの末尾に追加 */
$fp = fopen('data.txt', 'a+') or exit('error!');
flock($fp, LOCK_EX);
$no = 0;
while ($line = fgets($fp)) {
if (intval($line) > $no) {
$no = intval($line);
}
}
$no++;
fwrite($fp, "$no\t" . date('H:i:s') . "\n");
flock($fp, LOCK_UN);
fclose($fp);今のところ、こんな感じで。
tifos URL
こんばんわ。
何となくお気付きかと思いますが、fopen()の"w"モードは少々危険です。
特に「編集スクリプト」の場合、例えばfopen()後のfwrite()処理時にエラーでスクリプトが終了してしまうと…
ファイルの中身が空になったまま、文字通りthe endです。
ファイルロックの仕組みは、他プロセスからはロックしてくれますが、自プロセスのトラブルには無力です。
私もいろいろ試行錯誤の結果、編集の場合は、どんな瞬間にエラーで終了しても被害が最小限になるよう、
・"r+"モードのfopen()でファイルを開きっぱなしにする。(もちろん排他ロック)
・元データを消してしまわないようにファイルポインタを適切に操作しながら、上書き保存する。
という方法に落ち着きました。
ご参考まで。