Search A.I.
Menu
ホーム

メールマガジン ホームページプログラミングテク

Windowsテク
Javaアプレット サンプル
Java Q & A
JavaScript Q & A
Perl Q & A
Perl レッスン
PHP レッスン
PHPテク
MS-DOS コマンド集
UNIX コマンド集
SQL コマンド集
SEの基礎講座
WEBシステム開発受注します
]無料フォームメール送信サービス
リンク集
PHP レッスン

1. PHP の基礎
2. PHPの文法、条件式
3. PHPの文法、条件式 - 続き
4. 配列について
5. ハッシュ配列について
6. 関数について
7. 関数について - 続き
8. 文字列操作関数
9. 配列操作関数
10. ファイル操作
11. ファイル操作 - 続き
12. パラメータの受け渡し
13. クッキーとセッション
14. 総合練習
15. メール送信
16. ファイルアップロード
17. クラスについて
18. クラスについて - 続き
19. MySQL
20. MySQL - 続き(1)
21. MySQL - 続き(2)
22. PostgreSQL
23. 総合練習
24. 総合練習解答



11. ファイル操作 - 続き

今日は、ファイル操作の続きのご説明をいたします。

■ファイル操作関数
これまでに、いくつかのファイル操作関数が出てきましたが、その他のファイル
操作関数をご紹介します。

file_exists($fname) ファイルの存在を確認します。
filesize($fname) ファイルのサイズを確認します。
is_file($fname) ファイルかどうかを判定します。
is_dir($dir) ディレクトリかどうかを判定します。
is_readable($fname) ファイルが読み込み可能かを確認します。
is_writable($fname) ファイルが書き込み可能かを確認します。
unlink($fname1) 指定したファイルを削除します。
rename($fname1,$fname2)
ファイル名を$fname1から$fname2に変更します。
copy($fname1,$fname2)
ファイル$fname1を$fname2のファイル名でコピーします。

以下にサンプルを記述します。

-----------------------------------------------------------------
$filename = "test.txt";

// ファイルの存在確認
if (!file_exists($filename)) {
print "ファイルが見つかりません。 ".$filename;
exit;
}

// ファイルかどうかの判定
if (is_file($filename)) {
print $filename."はファイルです。<br>";
}
if (is_dir($filename)) {
print $filename."はディレクトリです。";
exit;
}

// 読み込み・書き込みの判定
if (is_readable($filename)) {
print $filename."は読み込み可能です。<br>";
}
if (is_writable($filename)) {
print $filename."は書き込み可能です。<br>";
}

// ファイルサイズ取得
print filesize($filename);

$filename2 = "test2.txt";
// ファイル名の変更
if (!rename($filename, $filename2)) {
print "リネーム失敗";
exit;
}

$filename3 = "test3.txt";
// ファイルのコピー
if (!copy($filename2, $filename3)) {
print "コピー失敗";
exit;
}

// ファイルの削除
unlink($filename2);
-----------------------------------------------------------------

file_exists()は、ファイルの存在を確認します。ディレクトリの存在確認にも
使えますが、ディレクトリなのかファイルなのかは、この関数では分かりません。

is_dir()またはis_file()関数を使用すれば、ファイルかディレクトリかの
判定ができます。

is_readable()は、ファイルが存在して、かつ読み込み可能な場合に真を返します。

is_writable()も同様に、ファイルが存在して、かつ書き込み可能な場合に、真を
返します。

rename()は、ファイル名を変更します。第1引数に、変更するファイル名、
第2引数に変更後のファイル名を指定します。成功すると、真が返ってきます。

copy()は、ファイルをコピーします。第1引数に、コピー元のファイル名、
第2引数にコピー先のファイル名を指定します。成功すると、真が返ってきます。

unlink()は、ファイルを削除します。成功すると真、失敗すると偽が返ってきます。

rename()やunlink()などは、ファイルオープンしてからクローズしていない状態で
実行するとエラーになりますので、注意してください。

上記を全て実行すると、test.txtのファイルがあった場合、test2.txtにリネーム
され、test3.txtにコピーされ、test2.txtが削除されますので、結局test3.txt
だけが残り、ファイルの情報が出力されます。

■ファイルロック
ファイル書き込み中に、別のユーザのアクセスによって、同時に同じファイルを
更新されると、ファイルが壊れたり、中身が消えたりしてしまいます。

そこで、誰かがファイル書き込み中のときは、ファイルロックして、他の人が
ファイルを更新できないようにします。

ここでは、簡単なファイルロック方法をご紹介します。
ファイルロックを行うには、flock()関数を使用します。
ただし、サーバによっては、flock関数が使用できないので、注意してください。

flock($fh, $lock) ファイルのロックや開放を行います。

第2引数には、設定するロック状態のフラグを指定します。

LOCK_SH : 1 共有ロック(読み込みは可能)
LOCK_EX : 2 排他ロック
LOCK_NB : 4 ロックなし
LOCK_UN : 8 ロック解除

PHPのバージョンによっては、これらの定数が定義されていない場合がありますが、
数値を直接指定しても同じです。。

-----------------------------------------------------------------
// 書き込みモードでファイルオープン
$fh = fopen($filename, 'w');
if (!$fh) {
print "ファイルオープンに失敗しました。 ".$filename;
exit;
}

// ファイルロック
flock($fh, LOCK_EX);

// ファイル書き込み
fwrite($fh, "TEST");

// ファイルロック解除
flock($fh, LOCK_UN);

// ファイルクローズ
fclose($fh);
-----------------------------------------------------------------

これで、一応ファイルロックされますが、これはまだ完璧ではありません。
ファイルオープン後にファイルロックしていますが、この処理の間でアクセス
があった場合に、同時にファイルオープンされてしまう可能性があるからです。

完全に回避するには、ロック用の一時ファイルを作成する方法がありますが、
これについては、別の機会にご説明します。

ここでは、上のサンプルを、さらに安全にしたものをご紹介します。

-----------------------------------------------------------------
// 追加書き込みモードでファイルオープン
$fh = fopen($filename, 'a');
if (!$fh) {
print "ファイルオープンに失敗しました。 ".$filename;
exit;
}

// ファイルロック
flock($fh, LOCK_EX);

// ファイルの中身を削除
ftruncate($fh, 0);

// ファイル書き込み
fwrite($fh, "TEST");

// ファイルロック解除
flock($fh, LOCK_UN);

// ファイルクローズ
fclose($fh);
-----------------------------------------------------------------

先ほどとの違いは、追加書き込みで開いてロックした後に、ファイル内容を削除
しているという点です。

ftruncate()は、第2引数で指定したバイト数にファイルを切り詰める関数です。
サンプルの場合、0 バイトに切り詰めることで、ファイル内容を削除しています。
ただし、このftruncate()もサーバによっては使用できない場合があるので、
注意してください。

ファイル書き込みモードでオープンしてしまうと、一旦ファイル内容がクリア
されてしまいますので、追加モードで開いてからロックした方が安全と言えます。

 

★今日のまとめサンプルプログラム
-----------------------------------------------------------------
<HTML>
<BODY>
<?

$filename = "test.txt";

// ファイルの存在確認
if (!file_exists($filename)) {
print "ファイルが見つかりません。 ".$filename;
exit;
}

// ファイルかどうかの判定
if (!is_file($filename)) {
print $filename."はファイルではありません。";
exit;
}

// 読み込み・書き込みの判定
if (!is_readable($filename)) {
print $filename."は読み込み可能ではありません。";
exit;
}
if (!is_writable($filename)) {
print $filename."は書き込み可能ではありません。";
exit;
}

// ファイルサイズ取得
$fsize = filesize($filename);

if ($fsize == 0) {
// 追加書き込みモードでファイルオープン
$fh = fopen($filename, 'a');
if (!$fh) {
print "ファイルオープンに失敗しました。 ".$filename;
exit;
}

// ファイルロック
flock($fh, LOCK_EX);

// ファイルの中身を削除
ftruncate($fh, 0);

// ファイル書き込み
fwrite($fh, "This is a sample file.\n");

// ファイルロック解除
flock($fh, LOCK_UN);

// ファイルクローズ
fclose($fh);
}

?>
</BODY>
</HTML>
-----------------------------------------------------------------

■解説
この処理は、text.txtファイルの存在を確認し、読み込み・書き込み可能で、
かつファイルサイズが 0 の場合に、ファイルロックして書き込みを行って
います。

test.txtがない場合は、空のファイルを書き込みオープンすることで、新しく
作成することもできます。

エラー時の処理などは、かなり省略していますが、実際にプログラムを書く
ときは、サイト毎に共通のエラー処理を決めるのが普通です。

 

★課題
1. 以下の処理を行うプログラムを作成してください。
(1) "test.tmp"ファイルの存在を判別
(2) "test.tmp"が存在する場合は、"エラー"を表示して終了
(3) "test.tmp"に現在時刻を書き込む(yyyy/mm/dd hh:mm:ss)
(4) "test.tmp"のファイルサイズが 0 かどうかを判別
(5) "test.tmp"のファイルサイズを取得
(6) "test.tmp"を削除する

2. 前回作成したアクセスカウンタのプログラムを変更し、ファイル書き込み時に
ファイルロックを行うように変更してください。

 

★前回の課題の解答
1. 簡易的なアクセスカウンタを作成してください。

→下のサンプルを参照してください。

-----------------------------------------------------------------
<HTML>
<BODY>
<?

$filename = './count.txt';

// 読み込みモードでファイルオープン
$fh = fopen($filename, 'r');
if (!$fh) {
print "ファイルオープンに失敗しました。 ".$filename;
exit;
}

// ファイル読み込み
while (!feof($fh)) {
$cnt = fgets($fh);
}

// ファイルクローズ
fclose($fh);

if ($cnt == "") {
$cnt = 0;
}

$cnt = $cnt + 1;

// 書き込みモードでファイルオープン
$fh = fopen($filename, 'w');
if (!$fh) {
print "ファイルオープンに失敗しました。 ".$filename;
exit;
}

// ファイル書き込み
fwrite($fh, $cnt);

// ファイルクローズ
fclose($fh);

print $cnt;

?>
</BODY>
</HTML>
-----------------------------------------------------------------

■解説
"count.txt"というファイルを作成して、PHPファイルと同じ場所に置いておきます。
UNIXの場合は、書き込みの権限を与える必要があります。

このファイルを読み込んで、一旦閉じて、書き込みで開きなおすという処理を
行います。

if ($cnt == "") {
$cnt = 0;
}
の部分は、なくても構いませんが、ファイルの中身がない場合は、0 から
カウントを始めます。

ファイルがない場合の処理もあると親切ですね。




前の章へ 次の章へ


このエントリーをはてなブックマークに追加


OfficeLance

お問い合わせはこちらから