自分用のメモが続くがPHP話。PHPで「入力されたデータを受けて、それをファイルに書き込んでいく」場合、ファイルの「開け方」と「入力の仕方」と「閉じ方」に注意が要る。
開け方。データを入力したいファイル先を「fopen(の「w」)」で開けた場合、開けた時点でファイル先の中身が消える。その後正常に書き込めればそれで問題ないんだが
何らかの理由で正常な書き込みが出来なかった場合には、ファイル先の中身が消えた状態、つまりファイルサイズが0になった状態でそのファイルが閉じられてしまう。
…つまり「データが消えたまま終わる」事になる。書き換える場合には「fopen(の「r+」)」を採用する。「rは読み書き専用」だが、そこにプラスが足されると
読み書き兼用の状態でファイルが開かれる事になる。何らかの理由で正常な書き込みが出来なかった場合でも、ファイル先の中身は残されたままになる。
そしてflockの「2」でロックを掛ける。PHPで「同じ機能」を指している関数。つまり「どっちでもいいですよ」とされている「エイリアス(別名)」に関して。
例えば「fwrite」と「fputs」の様なケース。その場合俺はスクリプトの記述内容が短くなる方、つまり「文字数の小さい関数」の方を使う。その場合には
「fputs」の方が1文字短いので俺はそっちを愛用する。そこまでこだわる。「俺以外の人が書いたスクリプトを、俺が使いづらいと感じる理由」の1つはそれ。
「ロックを掛ける」場合、英字の「lock_ex」が7文字掛かるのに対して「2」は1文字でいい。こちらの方が短くなる。まぁそう言う理由なんでこれ。短くて小さい方がいい。
開けたファイル先に中身を書き込む。書き込む時の順番は「ftruncate→rewind→fputs」ではなく「rewind→fputs→ftruncate(ftellを入れる)」の方がいい。
前者。ftruncateを掛けた時点でファイルサイズが0になる。その後fputsに何らかの理由で失敗した場合にはファイルサイズが0のままでファイルの中身が終わる。
後者。rewindを掛けてファイルポインタの位置を0にして、fputsでファイルに入れたいデータの中身を入力する。ftellでファイルポインタの「終点」を指定する。理に適う。
終点を指定する理由。ファイルを開いて、データを書き込んだそのファイル先の「書き込む前のデータが1200バイト」で「書き込んだ後のデータが1000バイト」
だとした場合。「1000バイトを書いた後、以前に残っていたデータの「1001バイトから1200バイトまで」が削りカスの様な状態で残ってしまう事になる。
つまり「ファイルの中身」が変になる。従って「1001バイトから1200バイト目までを『無かった事にする』」為に必要な関数が「ftruncate(ftellを入れる)」になる。
一般的には「ファイルを指定した長さに丸める」と説明されているんだが、この説明だと分かりづらい。「指定した長さから先の中身を無かった事にする」
こう書いた方が分かりやすい。「書き込む前<書き込んだ後 → 全てが上書きされるので記述自体に意味が薄くなる」「書き込む前>書き込んだ後 → カスを削る」
こうなる。そして最後は「ロックしたファイルを解除する」訳だが、「LOCK_UN→fclose」ではなく「fclose」だけで事足りる。「fcloseはロック解除も兼用している」から。
…但し。「2010年3月」にリリースされた「PHP 5.3.2」から「ファイルのリソースハンドルを閉じたときにロックを自動的に解放する機能が削除されました」
『ロックの解放は、常に手動で行わなければなりません』となっている。この日記を書いている現時点で使用しているサーバー内のPHPのバージョンは「5.2.10」。
だから今はそのバージョンではないとは言え、いずれは対応しないといけない訳ですな。そこら辺「バージョンの数字には気をつけましょう」と言うのが俺の感想。
俺の感覚は「サーバーを移転する、もしくはサーバー内のソフトのバージョンアップが行われて5.3.2よりも大きい数字のバージョンとなった場合には書き換える」にて。